Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Functional Library #76

Open
wants to merge 19 commits into
base: release-1.0.0
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions src/stdlib/ns/fn.es6
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
export default function(cheddar){
return cheddar.namespace([
["hook", cheddar.from(require("./fn/hook"))],
["fork", cheddar.from(require("./fn/fork"))],
["reflexive", cheddar.from(require("./fn/reflexive"))],
["dbl", cheddar.from(require("./fn/dbl"))],
["pref", cheddar.from(require("./fn/pref"))],
["insert", cheddar.from(require("./fn/insert"))],
["prefix", cheddar.from(require("./fn/prefix"))],
["id", cheddar.from(require("./fn/id"))],
["curry", cheddar.from(require("./fn/curry"))],
["bind", cheddar.from(require("./fn/bind"))],
["rev", cheddar.from(require("./fn/rev"))],
["repeat", cheddar.from(require("./fn/repeat"))],
["of", cheddar.from(require("./fn/of"))]
]);
}
29 changes: 29 additions & 0 deletions src/stdlib/ns/fn/bind.es6
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
export default function bind(cheddar) {
return new cheddar.func(
[
["args", {Splat: true}]
],
function(scope, input){
let args = input("args").value;
if(args[0] instanceof cheddar.func){
let f = args.shift();
return new cheddar.func(
[["b", {Splat: true}]],
function(s, k){
return f.exec(k("b").value.concat(args), null);
}
);
} else if(args[args.length - 1] instanceof cheddar.func){
let f = args.pop();
return new cheddar.func(
[["b", {Splat: true}]],
function(s, k){
return f.exec(args.concat(k("b").value), null);
}
);
} else {
return "Expected function as first or last argument.";
}
}
);
}
19 changes: 19 additions & 0 deletions src/stdlib/ns/fn/curry.es6
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
export default function curry(cheddar) {
return new cheddar.func(
[
["f", { Type: cheddar.func }],
["a", {}]
],
function(scope, input){
return new cheddar.func(
[["b", {}]],
function(s, k){
let f = input("f");
let a = input("a");
let b = k("b");
return f.exec([a, b], null);
}
)
}
);
}
26 changes: 26 additions & 0 deletions src/stdlib/ns/fn/fork.es6
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
export default function fork(cheddar) {
return new cheddar.func(
[
["f", { Type: cheddar.func }],
["g", { Type: cheddar.func }],
["h", { Type: cheddar.func }]
],
function(scope, input){
return new cheddar.func(
[["args", {Splat: true}]],
function(s, k){
let args = k("args").value;

let f = input("f");
let g = input("g");
let h = input("h");

return g.exec([
f.exec(args, null),
h.exec(args, null)
], null);
}
)
}
);
}
27 changes: 27 additions & 0 deletions src/stdlib/ns/fn/hook.es6
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
export default function hook(cheddar) {
return new cheddar.func(
[
["f", { Type: cheddar.func }],
["g", { Type: cheddar.func }]
],
function(scope, input, args){
if(args.length !== 2)
return `Expected 2 arguments, received ${args.length}.`;

return new cheddar.func(
[["args", {Splat: true}]],
function(s, k){
let args = k("args").value;

if(args.length > 2 || !args.length)
return `Expected 1 or 2 args, received ${args.length || "none"}`;

let f = input("f");
let g = input("g");

return f.exec([args[0], g.exec([args.length === 1 ? args[0] : args[1]], null)], null);
}
)
}
);
}
8 changes: 8 additions & 0 deletions src/stdlib/ns/fn/id.es6
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
export default function id(cheddar) {
return new cheddar.func(
[["a", { Type: cheddar.func }]],
function(scope, input){
return input("a");
}
)
}
25 changes: 25 additions & 0 deletions src/stdlib/ns/fn/insert.es6
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
export default function insert(cheddar) {
return new cheddar.func(
[
["f", { Type: cheddar.func }],
],
function(scope, input){
return new cheddar.func(
[["array", {
Type: cheddar.array
}]],
function(s, k){
let arr = k("array");
let f = input("f");

if(arr.length === 1)
return arr;

// console.log("DEBUG:",arr);

return arr.value.reduce((prev, cur) => f.exec([prev, cur], null));
}
)
}
);
}
51 changes: 51 additions & 0 deletions src/stdlib/ns/fn/of.es6
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import { UOP, OP } from "../../../tokenizer/consts/ops";
import fork from "./fork";

const ops = [
"+", "*", "**", "-", "^",
"&", "|", "/", "%", "@\""
]; // TODO: make dynamic

const parse = (str) => {
let tokens = [];
for(let i = 0; i < str.length; i++){
if(!ops.some(x => x[0] === str[i])) continue;

let build = "";
while(ops.some(x => x.indexOf(build + str[i]) >= 0)){
build += str[i++];
}
i--;
tokens.push(build);
}
return tokens;
}

export default function insert(cheddar) {
return new cheddar.func(
[
["str", {
Type: cheddar.string
}],
],
function(scope, input){
let str = input("str");
let toks = parse(str.value);
if(toks.length !== 3){
return "I haven't implemented this yet.";
}
return fork.exec(...toks.map(e =>
new cheddar.func(
["LHS", { }],
["RHS", { Optional: true }],
function(_scope, _input){
let LHS = input("LHS");
let RHS = input("RHS");

return LHS.Operator.get(e)(RHS ? LHS : null, RHS || LHS);
}
)
), null);
}
);
}
12 changes: 12 additions & 0 deletions src/stdlib/ns/fn/pref.es6
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
export default function pref(cheddar) {
return new cheddar.func(
[
["array", {}],
],
function(scope, input){
return cheddar.init(cheddar.array, ...input("array").value.map(
(e, i, a) => cheddar.init(cheddar.array, ...a.slice(0, i + 1))
));
}
);
}
18 changes: 18 additions & 0 deletions src/stdlib/ns/fn/prefix.es6
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
export default function prefix(cheddar) {
return new cheddar.func(
[["f", { Type: cheddar.func }]],
function(scope, k){
return new cheddar.func(
[["array", {}]],
function(s, input){
let f = k("f");
return cheddar.init(cheddar.array, ...input("array").value.map(
(e, i, a) => f.exec([
cheddar.init(cheddar.array, ...a.slice(0, i + 1))
], null)
));
}
);
}
)
}
17 changes: 17 additions & 0 deletions src/stdlib/ns/fn/reflexive.es6
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
export default function reflexive(cheddar) {
return new cheddar.func(
[
["f", { Type: cheddar.func }],
],
function(scope, input){
return new cheddar.func(
[["a", {}]],
function(s, k){
let f = input("f");

return f.exec(Array(f.args.length).fill(k("a")), null);
}
)
}
);
}
27 changes: 27 additions & 0 deletions src/stdlib/ns/fn/repeat.es6
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
export default function repeat(cheddar) {
return new cheddar.func(
[
["f", { Type: cheddar.func }],
["n", {}]
],
function(scope, input){
return new cheddar.func(
[["args", { Splat: true }]],
function(s, k){
let f = input("f");
let n = input("n").value;
let args = k("args");
if(n === 0)
return args;

args = args.value;
let res = f.exec(args, null);
while(--n > 0){
res = f.exec([res], null);
}
return res;
}
)
}
);
}
16 changes: 16 additions & 0 deletions src/stdlib/ns/fn/rev.es6
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
export default function rev(cheddar) {
return new cheddar.func(
[
["f", { Type: cheddar.func }]
],
function(scope, input){
return new cheddar.func(
[["a", { Splat: true }]],
function(s, k){
let a = k("a");
return input("f").exec(a.value.reverse(), null);
}
)
}
);
}
8 changes: 5 additions & 3 deletions src/stdlib/stdlib.es6
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,11 @@ STDLIB.Item("Math");
STDLIB.Item("Rational");

// Interface Libraries
STDLIB.Item("Encoding");
STDLIB.Item("Buffer");
STDLIB.Item("IO", true);
STDLIB.Item("Encoding", require('./ns/Encoding'));
STDLIB.Item("Buffer", require('./ns/Buffer'));
STDLIB.Item("IO", require('./ns/IO'));
STDLIB.Item("fn", require("./ns/fn"));
//STDLIB.Item("HTTP", require('./ns/HTTP'));

/** Primitives **/
STDLIB.p("String", API.string);
Expand Down
3 changes: 3 additions & 0 deletions test.cdr
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
var fib = (n) -> {
print n
}
22 changes: 22 additions & 0 deletions test/tests/stdlib/fn.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
var TestCheddarFrom = require('../globals').TestCheddarFrom;
var chai = require('chai');

describe("fn", function(){
describe("reflexive", function(){
it("should work", TestCheddarFrom.Code(
"fn.reflexive((+))(3)",
"6"
));
it("should work", TestCheddarFrom.Code(
"fn.reflexive((*))(3)",
"9"
));
});

describe("hook", function(){
it("should work", TestCheddarFrom.Code(
"fn.hook((+),(sqrt),(-))(4)",
"6"
));
});
});