mirror of
https://github.com/zaphar/ucg.git
synced 2025-07-22 18:19:54 -04:00
REFACTOR: The great renaming macro -> func.
This commit is contained in:
parent
ff57c229dc
commit
f1c7d76fdd
@ -1,4 +1,4 @@
|
|||||||
let bucketbase = macro(name, project, location) => {
|
let bucketbase = func (name, project, location) => {
|
||||||
name = name,
|
name = name,
|
||||||
type = "storage.v1.bucket",
|
type = "storage.v1.bucket",
|
||||||
properties = {
|
properties = {
|
||||||
@ -25,16 +25,15 @@ let bucketbase = macro(name, project, location) => {
|
|||||||
role = "READER",
|
role = "READER",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
let bucketSelfLink = macro(bucket) => {
|
let bucketSelfLink = func (bucket) => {
|
||||||
name = "@selfLink" % (bucket),
|
name = "@selfLink" % (bucket),
|
||||||
value = "https://console.cloud.google.com/storage/browser/@" % (bucket),
|
value = "https://console.cloud.google.com/storage/browser/@" % (bucket),
|
||||||
};
|
};
|
||||||
|
|
||||||
let bucketGsLink = macro(bucket) => {
|
let bucketGsLink = func (bucket) => {
|
||||||
name = "@gsLink" % (bucket),
|
name = "@gsLink" % (bucket),
|
||||||
value = "gs://@" % (bucket),
|
value = "gs://@" % (bucket),
|
||||||
};
|
};
|
@ -1,4 +1,4 @@
|
|||||||
assert {macro };
|
assert {func };
|
||||||
assert {{ foo = hello world}};
|
assert {{ foo = hello world}};
|
||||||
assert {{ foo = "hello world"};
|
assert {{ foo = "hello world"};
|
||||||
assert {{ = }};
|
assert {{ = }};
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
let port = 3306;
|
let port = 3306;
|
||||||
|
|
||||||
let mk_site_config = macro(hostname, port) => {
|
let mk_site_config = func (hostname, port) => {
|
||||||
base_url = "https://@/" % (hostname),
|
base_url = "https://@/" % (hostname),
|
||||||
port = port,
|
port = port,
|
||||||
dbs = [],
|
dbs = [],
|
||||||
|
@ -6,7 +6,7 @@ let dbhost2 = "db2.prod.net";
|
|||||||
let dbname = "testdb";
|
let dbname = "testdb";
|
||||||
|
|
||||||
// Constructor for database connection strings.
|
// Constructor for database connection strings.
|
||||||
let mk_db_conn = macro (host, port, db) => {
|
let mk_db_conn = func (host, port, db) => {
|
||||||
host = host,
|
host = host,
|
||||||
port = port,
|
port = port,
|
||||||
db = db,
|
db = db,
|
||||||
@ -19,7 +19,7 @@ let db_conn2 = mk_db_conn(dbhost2, shared.port, dbname);
|
|||||||
// We have two database connections in a list
|
// We have two database connections in a list
|
||||||
let db_conn_list = [db_conn1, db_conn2];
|
let db_conn_list = [db_conn1, db_conn2];
|
||||||
|
|
||||||
let connstr_mapper = macro (item) => {
|
let connstr_mapper = func (item) => {
|
||||||
str = item.conn_string
|
str = item.conn_string
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -6,7 +6,7 @@ let dbhost2 = "db2.prod.net";
|
|||||||
let dbname = "testdb";
|
let dbname = "testdb";
|
||||||
|
|
||||||
// Constructor for database connection strings.
|
// Constructor for database connection strings.
|
||||||
let mk_db_conn = macro (host, port, db) => {
|
let mk_db_conn = func (host, port, db) => {
|
||||||
host = host,
|
host = host,
|
||||||
port = port,
|
port = port,
|
||||||
db = db,
|
db = db,
|
||||||
@ -19,7 +19,7 @@ let db_conn2 = mk_db_conn(dbhost2, shared.port, dbname);
|
|||||||
// We have two database connections in a list
|
// We have two database connections in a list
|
||||||
let db_conn_list = [db_conn1, db_conn2];
|
let db_conn_list = [db_conn1, db_conn2];
|
||||||
|
|
||||||
let connstr_mapper = macro (item) => {
|
let connstr_mapper = func (item) => {
|
||||||
str = item.conn_string
|
str = item.conn_string
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -3,14 +3,14 @@
|
|||||||
let list1 = [1, 2, 3, 4];
|
let list1 = [1, 2, 3, 4];
|
||||||
let list2 = ["foo", "bar", "foo", "bar"];
|
let list2 = ["foo", "bar", "foo", "bar"];
|
||||||
|
|
||||||
let mapper = macro(item) => item + 1;
|
let mapper = func (item) => item + 1;
|
||||||
let filtrator = macro(item) => select item, NULL, {
|
let filtrator = func (item) => select item, NULL, {
|
||||||
foo = item,
|
foo = item,
|
||||||
};
|
};
|
||||||
|
|
||||||
let boolfiltrator = macro(item) => item < 5;
|
let boolfiltrator = func (item) => item < 5;
|
||||||
|
|
||||||
let identity_list_reducer = macro(acc, item) => acc + [item];
|
let identity_list_reducer = func (acc, item) => acc + [item];
|
||||||
|
|
||||||
assert {
|
assert {
|
||||||
ok = reduce identity_list_reducer [], list1 == list1,
|
ok = reduce identity_list_reducer [], list1 == list1,
|
||||||
@ -26,7 +26,7 @@ assert {
|
|||||||
desc = "reduce identity_list_reducer [], (nested_list.list) == list1",
|
desc = "reduce identity_list_reducer [], (nested_list.list) == list1",
|
||||||
};
|
};
|
||||||
|
|
||||||
let list_reducer = macro(acc, item) => acc + item;
|
let list_reducer = func (acc, item) => acc + item;
|
||||||
|
|
||||||
assert {
|
assert {
|
||||||
ok = reduce list_reducer 0, list1 == 0 + 1 + 2 + 3 + 4,
|
ok = reduce list_reducer 0, list1 == 0 + 1 + 2 + 3 + 4,
|
||||||
@ -46,7 +46,7 @@ assert {
|
|||||||
desc = "map mapper [1, 2, 3, 4] == [2, 3, 4, 5]",
|
desc = "map mapper [1, 2, 3, 4] == [2, 3, 4, 5]",
|
||||||
};
|
};
|
||||||
|
|
||||||
let s_mapper = macro(arg) => arg + ",";
|
let s_mapper = func (arg) => arg + ",";
|
||||||
|
|
||||||
assert {
|
assert {
|
||||||
ok = map s_mapper "foo" == "f,o,o,",
|
ok = map s_mapper "foo" == "f,o,o,",
|
||||||
@ -77,14 +77,14 @@ let test_tpl = {
|
|||||||
quux = "baz",
|
quux = "baz",
|
||||||
};
|
};
|
||||||
|
|
||||||
let identity_tpl_mapper = macro(name, val) => [name, val];
|
let identity_tpl_mapper = func (name, val) => [name, val];
|
||||||
|
|
||||||
assert {
|
assert {
|
||||||
ok = map identity_tpl_mapper test_tpl == test_tpl,
|
ok = map identity_tpl_mapper test_tpl == test_tpl,
|
||||||
desc = "map identity_tpl_mapper test_tpl == test_tpl",
|
desc = "map identity_tpl_mapper test_tpl == test_tpl",
|
||||||
};
|
};
|
||||||
|
|
||||||
let tpl_mapper = macro(name, val) => select name, [name, val], {
|
let tpl_mapper = func (name, val) => select name, [name, val], {
|
||||||
"foo" = ["foo", "barbar"],
|
"foo" = ["foo", "barbar"],
|
||||||
quux = ["cute", "pygmy"],
|
quux = ["cute", "pygmy"],
|
||||||
};
|
};
|
||||||
@ -94,10 +94,10 @@ assert {
|
|||||||
desc = "map tpl_mapper test_tpl == {foo = \"barbar\", cute = \"pygmy\"}",
|
desc = "map tpl_mapper test_tpl == {foo = \"barbar\", cute = \"pygmy\"}",
|
||||||
};
|
};
|
||||||
|
|
||||||
let identity_tpl_filter = macro(name, val) => true;
|
let identity_tpl_filter = func (name, val) => true;
|
||||||
|
|
||||||
// strip out foo field
|
// strip out foo field
|
||||||
let tpl_filter = macro(name, val) => name != "foo";
|
let tpl_filter = func (name, val) => name != "foo";
|
||||||
|
|
||||||
assert {
|
assert {
|
||||||
ok = filter identity_tpl_filter test_tpl == test_tpl,
|
ok = filter identity_tpl_filter test_tpl == test_tpl,
|
||||||
@ -109,14 +109,14 @@ assert {
|
|||||||
desc = "filter tpl_filter test_tpl == { quux = \"baz\" }",
|
desc = "filter tpl_filter test_tpl == { quux = \"baz\" }",
|
||||||
};
|
};
|
||||||
|
|
||||||
let o_str_filter = macro(s) => s != "o";
|
let o_str_filter = func (s) => s != "o";
|
||||||
|
|
||||||
assert {
|
assert {
|
||||||
ok = filter o_str_filter "foobar" == "fbar",
|
ok = filter o_str_filter "foobar" == "fbar",
|
||||||
desc = "We can strip out characters",
|
desc = "We can strip out characters",
|
||||||
};
|
};
|
||||||
|
|
||||||
let tpl_reducer = macro(acc, name, val) => acc{
|
let tpl_reducer = func (acc, name, val) => acc{
|
||||||
keys = self.keys + [name],
|
keys = self.keys + [name],
|
||||||
vals = self.vals + [val],
|
vals = self.vals + [val],
|
||||||
};
|
};
|
||||||
@ -126,14 +126,14 @@ assert {
|
|||||||
desc = "reduce tpl_reducer {keys = [], vals = []}, test_tpl == {keys = [\"foo\", \"quux\"], vals = [\"bar\", \"baz\"]}",
|
desc = "reduce tpl_reducer {keys = [], vals = []}, test_tpl == {keys = [\"foo\", \"quux\"], vals = [\"bar\", \"baz\"]}",
|
||||||
};
|
};
|
||||||
|
|
||||||
let str_identity_reducer = macro(acc, s) => acc + s;
|
let str_identity_reducer = func (acc, s) => acc + s;
|
||||||
|
|
||||||
assert {
|
assert {
|
||||||
ok = reduce str_identity_reducer "", "foo" == "foo",
|
ok = reduce str_identity_reducer "", "foo" == "foo",
|
||||||
desc = "identity reducer copies string",
|
desc = "identity reducer copies string",
|
||||||
};
|
};
|
||||||
|
|
||||||
let char_iter = macro(acc, s) => acc + [s];
|
let char_iter = func (acc, s) => acc + [s];
|
||||||
|
|
||||||
assert {
|
assert {
|
||||||
ok = reduce char_iter [], "foo" == ["f", "o", "o"],
|
ok = reduce char_iter [], "foo" == ["f", "o", "o"],
|
||||||
|
@ -1,14 +1,14 @@
|
|||||||
let noargmacro = macro() => {
|
let noargmacro = func () => {
|
||||||
field1 = "value",
|
field1 = "value",
|
||||||
};
|
};
|
||||||
|
|
||||||
let simplemacro = macro(arg1, arg2, arg3) => {
|
let simplemacro = func (arg1, arg2, arg3) => {
|
||||||
field1 = arg1,
|
field1 = arg1,
|
||||||
field2 = arg2,
|
field2 = arg2,
|
||||||
field3 = arg3,
|
field3 = arg3,
|
||||||
};
|
};
|
||||||
|
|
||||||
let cplxmacro = macro(argint, argstr, argfloat) => {
|
let cplxmacro = func (argint, argstr, argfloat) => {
|
||||||
field1 = argint + 1,
|
field1 = argint + 1,
|
||||||
field2 = argstr + " are here",
|
field2 = argstr + " are here",
|
||||||
field3 = argfloat - 1.0,
|
field3 = argfloat - 1.0,
|
||||||
@ -53,7 +53,7 @@ assert {
|
|||||||
desc = "cplxresult.boolfield == true",
|
desc = "cplxresult.boolfield == true",
|
||||||
};
|
};
|
||||||
|
|
||||||
let macro_tpl_arg = macro(tpl) => {
|
let macro_tpl_arg = func (tpl) => {
|
||||||
result = tpl.field,
|
result = tpl.field,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -68,7 +68,7 @@ assert {
|
|||||||
|
|
||||||
let closed_over = "foo";
|
let closed_over = "foo";
|
||||||
|
|
||||||
let closure = macro(arg1) => {
|
let closure = func (arg1) => {
|
||||||
result = closed_over + arg1,
|
result = closed_over + arg1,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -77,7 +77,7 @@ assert {
|
|||||||
desc = "we closed over closed_over and got @" % (closure("bar").result),
|
desc = "we closed over closed_over and got @" % (closure("bar").result),
|
||||||
};
|
};
|
||||||
|
|
||||||
let concat = macro(arg1, arg2) => arg1 + arg2;
|
let concat = func (arg1, arg2) => arg1 + arg2;
|
||||||
|
|
||||||
assert {
|
assert {
|
||||||
ok = concat("foo", "bar") == "foobar",
|
ok = concat("foo", "bar") == "foobar",
|
||||||
|
@ -20,28 +20,28 @@ assert {
|
|||||||
desc = "defaultgot == \"OOPS\"",
|
desc = "defaultgot == \"OOPS\"",
|
||||||
};
|
};
|
||||||
|
|
||||||
// select inside a macro
|
// select inside a function
|
||||||
|
|
||||||
let condmacro = macro(arg) => {
|
let condfunc = func (arg) => {
|
||||||
output = select arg, NULL, {
|
output = select arg, NULL, {
|
||||||
opt1 = "yay",
|
opt1 = "yay",
|
||||||
opt2 = "boo",
|
opt2 = "boo",
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
let result = condmacro("opt1");
|
let result = condfunc("opt1");
|
||||||
|
|
||||||
assert {
|
assert {
|
||||||
ok = condmacro("opt1") == {output = "yay"},
|
ok = condfunc("opt1") == {output = "yay"},
|
||||||
desc = "condmacro(\"opt1\") == {output = \"yay\"}",
|
desc = "condfunc(\"opt1\") == {output = \"yay\"}",
|
||||||
};
|
};
|
||||||
assert {
|
assert {
|
||||||
ok = condmacro("opt2") == {output = "boo"},
|
ok = condfunc("opt2") == {output = "boo"},
|
||||||
desc = "condmacro(\"opt2\") == {output = \"boo\"}",
|
desc = "condfunc(\"opt2\") == {output = \"boo\"}",
|
||||||
};
|
};
|
||||||
assert {
|
assert {
|
||||||
ok = condmacro("invalid") == {output = NULL},
|
ok = condfunc("invalid") == {output = NULL},
|
||||||
desc = "condmacro(\"invalid\") == {output = NULL}",
|
desc = "condfunc(\"invalid\") == {output = NULL}",
|
||||||
};
|
};
|
||||||
|
|
||||||
let iflike = select true, "default", {
|
let iflike = select true, "default", {
|
||||||
|
@ -6,7 +6,7 @@ let tuple = {
|
|||||||
deeplist = ["foo", "bar"],
|
deeplist = ["foo", "bar"],
|
||||||
};
|
};
|
||||||
|
|
||||||
let testmacro = macro(arg) => {
|
let testfunc = func (arg) => {
|
||||||
output = arg,
|
output = arg,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -47,12 +47,12 @@ assert {
|
|||||||
desc = "[\"one\", \"two\", \"three\"].0 == \"one\"",
|
desc = "[\"one\", \"two\", \"three\"].0 == \"one\"",
|
||||||
};
|
};
|
||||||
|
|
||||||
let macro_for_test = macro() => {
|
let func_for_test = func () => {
|
||||||
foo = "bar",
|
foo = "bar",
|
||||||
};
|
};
|
||||||
assert {
|
assert {
|
||||||
ok = macro_for_test().foo == "bar",
|
ok = func_for_test().foo == "bar",
|
||||||
desc = "macro_for_test().foo == \"bar\"",
|
desc = "func_for_test().foo == \"bar\"",
|
||||||
};
|
};
|
||||||
|
|
||||||
let mymodule = module { foo = "bar" } => {
|
let mymodule = module { foo = "bar" } => {
|
||||||
|
@ -31,13 +31,13 @@ assert t.not_ok{
|
|||||||
};
|
};
|
||||||
|
|
||||||
assert t.ok{
|
assert t.ok{
|
||||||
test = (macro(arg) => arg) is "macro",
|
test = (func(arg) => arg) is "func",
|
||||||
desc = "found a macro",
|
desc = "found a func",
|
||||||
};
|
};
|
||||||
|
|
||||||
assert t.not_ok{
|
assert t.not_ok{
|
||||||
test = (macro(arg) => arg) is "list",
|
test = (func(arg) => arg) is "list",
|
||||||
desc = "a macro is not a list",
|
desc = "a func is not a list",
|
||||||
};
|
};
|
||||||
|
|
||||||
assert t.ok{
|
assert t.ok{
|
||||||
@ -46,11 +46,11 @@ assert t.ok{
|
|||||||
};
|
};
|
||||||
|
|
||||||
assert t.not_ok{
|
assert t.not_ok{
|
||||||
test = module{} => {} is "macro",
|
test = module{} => {} is "func",
|
||||||
desc = "a module is not a macro",
|
desc = "a module is not a func",
|
||||||
};
|
};
|
||||||
|
|
||||||
let foo_check = macro(val) => (foo in val) && (val.foo is "str");
|
let foo_check = func (val) => (foo in val) && (val.foo is "str");
|
||||||
|
|
||||||
assert t.ok{
|
assert t.ok{
|
||||||
test = foo_check({foo="bar"}),
|
test = foo_check({foo="bar"}),
|
||||||
|
@ -289,7 +289,7 @@ impl Value {
|
|||||||
/// defined.
|
/// defined.
|
||||||
#[derive(PartialEq, Debug, Clone)]
|
#[derive(PartialEq, Debug, Clone)]
|
||||||
pub struct CallDef {
|
pub struct CallDef {
|
||||||
pub macroref: Value,
|
pub funcref: Value,
|
||||||
pub arglist: Vec<Expression>,
|
pub arglist: Vec<Expression>,
|
||||||
pub pos: Position,
|
pub pos: Position,
|
||||||
}
|
}
|
||||||
@ -372,11 +372,11 @@ impl<'a> From<&'a PositionedItem<String>> for PositionedItem<String> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Encodes a macro expression in the UCG AST..
|
/// Encodes a func expression in the UCG AST..
|
||||||
///
|
///
|
||||||
/// A macro is a pure function over a tuple.
|
/// A func is a pure function over a tuple.
|
||||||
#[derive(PartialEq, Debug, Clone)]
|
#[derive(PartialEq, Debug, Clone)]
|
||||||
pub struct MacroDef {
|
pub struct FuncDef {
|
||||||
pub scope: Option<Scope>,
|
pub scope: Option<Scope>,
|
||||||
pub argdefs: Vec<PositionedItem<String>>,
|
pub argdefs: Vec<PositionedItem<String>>,
|
||||||
pub fields: Box<Expression>,
|
pub fields: Box<Expression>,
|
||||||
@ -491,7 +491,7 @@ pub enum FuncOpDef {
|
|||||||
|
|
||||||
#[derive(Debug, PartialEq, Clone)]
|
#[derive(Debug, PartialEq, Clone)]
|
||||||
pub struct ReduceOpDef {
|
pub struct ReduceOpDef {
|
||||||
pub mac: PositionedItem<String>,
|
pub func: PositionedItem<String>,
|
||||||
pub acc: Box<Expression>,
|
pub acc: Box<Expression>,
|
||||||
pub target: Box<Expression>,
|
pub target: Box<Expression>,
|
||||||
pub pos: Position,
|
pub pos: Position,
|
||||||
@ -500,7 +500,7 @@ pub struct ReduceOpDef {
|
|||||||
/// MapFilterOpDef implements the list operations in the UCG AST.
|
/// MapFilterOpDef implements the list operations in the UCG AST.
|
||||||
#[derive(Debug, PartialEq, Clone)]
|
#[derive(Debug, PartialEq, Clone)]
|
||||||
pub struct MapFilterOpDef {
|
pub struct MapFilterOpDef {
|
||||||
pub mac: PositionedItem<String>,
|
pub func: PositionedItem<String>,
|
||||||
pub target: Box<Expression>,
|
pub target: Box<Expression>,
|
||||||
pub pos: Position,
|
pub pos: Position,
|
||||||
}
|
}
|
||||||
@ -626,7 +626,7 @@ pub enum Expression {
|
|||||||
Include(IncludeDef),
|
Include(IncludeDef),
|
||||||
Import(ImportDef),
|
Import(ImportDef),
|
||||||
Call(CallDef),
|
Call(CallDef),
|
||||||
Macro(MacroDef),
|
Func(FuncDef),
|
||||||
Select(SelectDef),
|
Select(SelectDef),
|
||||||
FuncOp(FuncOpDef),
|
FuncOp(FuncOpDef),
|
||||||
Module(ModuleDef),
|
Module(ModuleDef),
|
||||||
@ -646,7 +646,7 @@ impl Expression {
|
|||||||
&Expression::Grouped(ref expr) => expr.pos(),
|
&Expression::Grouped(ref expr) => expr.pos(),
|
||||||
&Expression::Format(ref def) => &def.pos,
|
&Expression::Format(ref def) => &def.pos,
|
||||||
&Expression::Call(ref def) => &def.pos,
|
&Expression::Call(ref def) => &def.pos,
|
||||||
&Expression::Macro(ref def) => &def.pos,
|
&Expression::Func(ref def) => &def.pos,
|
||||||
&Expression::Module(ref def) => &def.pos,
|
&Expression::Module(ref def) => &def.pos,
|
||||||
&Expression::Select(ref def) => &def.pos,
|
&Expression::Select(ref def) => &def.pos,
|
||||||
&Expression::FuncOp(ref def) => def.pos(),
|
&Expression::FuncOp(ref def) => def.pos(),
|
||||||
@ -685,8 +685,8 @@ impl fmt::Display for Expression {
|
|||||||
&Expression::Call(_) => {
|
&Expression::Call(_) => {
|
||||||
write!(w, "<MacroCall>")?;
|
write!(w, "<MacroCall>")?;
|
||||||
}
|
}
|
||||||
&Expression::Macro(_) => {
|
&Expression::Func(_) => {
|
||||||
write!(w, "<Macro>")?;
|
write!(w, "<Func>")?;
|
||||||
}
|
}
|
||||||
&Expression::Module(_) => {
|
&Expression::Module(_) => {
|
||||||
write!(w, "<Module>")?;
|
write!(w, "<Module>")?;
|
||||||
|
@ -89,7 +89,7 @@ impl<'a> AstWalker<'a> {
|
|||||||
Expression::Grouped(ref mut expr) => {
|
Expression::Grouped(ref mut expr) => {
|
||||||
self.walk_expression(expr);
|
self.walk_expression(expr);
|
||||||
}
|
}
|
||||||
Expression::Macro(ref mut def) => self.walk_expression(def.fields.as_mut()),
|
Expression::Func(ref mut def) => self.walk_expression(def.fields.as_mut()),
|
||||||
Expression::Module(ref mut def) => {
|
Expression::Module(ref mut def) => {
|
||||||
self.walk_fieldset(&mut def.arg_set);
|
self.walk_fieldset(&mut def.arg_set);
|
||||||
for stmt in def.statements.iter_mut() {
|
for stmt in def.statements.iter_mut() {
|
||||||
|
@ -45,7 +45,7 @@ fn test_comparisons() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_macros() {
|
fn test_funcs() {
|
||||||
assert_build(include_str!("../../integration_tests/macros_test.ucg"));
|
assert_build(include_str!("../../integration_tests/macros_test.ucg"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,7 +20,7 @@ pub enum Val {
|
|||||||
List(Vec<Rc<Val>>),
|
List(Vec<Rc<Val>>),
|
||||||
Tuple(Vec<(PositionedItem<String>, Rc<Val>)>),
|
Tuple(Vec<(PositionedItem<String>, Rc<Val>)>),
|
||||||
Env(Vec<(String, String)>),
|
Env(Vec<(String, String)>),
|
||||||
Macro(MacroDef),
|
Func(FuncDef),
|
||||||
Module(ModuleDef),
|
Module(ModuleDef),
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -36,7 +36,7 @@ impl Val {
|
|||||||
&Val::List(_) => "List".to_string(),
|
&Val::List(_) => "List".to_string(),
|
||||||
&Val::Tuple(_) => "Tuple".to_string(),
|
&Val::Tuple(_) => "Tuple".to_string(),
|
||||||
&Val::Env(_) => "Env".to_string(),
|
&Val::Env(_) => "Env".to_string(),
|
||||||
&Val::Macro(_) => "Macro".to_string(),
|
&Val::Func(_) => "Func".to_string(),
|
||||||
&Val::Module(_) => "Module".to_string(),
|
&Val::Module(_) => "Module".to_string(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -54,7 +54,7 @@ impl Val {
|
|||||||
&Val::List(_),
|
&Val::List(_),
|
||||||
&Val::Tuple(_),
|
&Val::Tuple(_),
|
||||||
&Val::Env(_),
|
&Val::Env(_),
|
||||||
&Val::Macro(_),
|
&Val::Func(_),
|
||||||
&Val::Module(_)
|
&Val::Module(_)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -99,8 +99,8 @@ impl Val {
|
|||||||
Ok(true)
|
Ok(true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
(&Val::Macro(_), &Val::Macro(_)) => Err(error::BuildError::new(
|
(&Val::Func(_), &Val::Func(_)) => Err(error::BuildError::new(
|
||||||
"Macros are not comparable",
|
"Func are not comparable",
|
||||||
error::ErrorType::TypeFail,
|
error::ErrorType::TypeFail,
|
||||||
pos,
|
pos,
|
||||||
)),
|
)),
|
||||||
@ -185,8 +185,8 @@ impl Val {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_macro(&self) -> bool {
|
pub fn is_func(&self) -> bool {
|
||||||
if let &Val::Macro(_) = self {
|
if let &Val::Func(_) = self {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@ -222,7 +222,7 @@ impl Display for Val {
|
|||||||
}
|
}
|
||||||
write!(f, "]")
|
write!(f, "]")
|
||||||
}
|
}
|
||||||
&Val::Macro(_) => write!(f, "Macro(..)"),
|
&Val::Func(_) => write!(f, "Func(..)"),
|
||||||
&Val::Module(_) => write!(f, "Module{{..}}"),
|
&Val::Module(_) => write!(f, "Module{{..}}"),
|
||||||
&Val::Tuple(ref def) => {
|
&Val::Tuple(ref def) => {
|
||||||
write!(f, "{{\n")?;
|
write!(f, "{{\n")?;
|
||||||
|
@ -49,21 +49,21 @@ enum ProcessingOpType {
|
|||||||
Filter,
|
Filter,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MacroDef {
|
impl FuncDef {
|
||||||
/// Expands a ucg Macro using the given arguments into a new Tuple.
|
/// Expands a ucg function using the given arguments into a new Tuple.
|
||||||
pub fn eval(
|
pub fn eval(
|
||||||
&self,
|
&self,
|
||||||
// TODO(jwall): This should come from the macrodef instead.
|
// TODO(jwall): This should come from the FuncDef instead.
|
||||||
root: PathBuf,
|
root: PathBuf,
|
||||||
parent_builder: &FileBuilder,
|
parent_builder: &FileBuilder,
|
||||||
mut args: Vec<Rc<Val>>,
|
mut args: Vec<Rc<Val>>,
|
||||||
) -> Result<Rc<Val>, Box<dyn Error>> {
|
) -> Result<Rc<Val>, Box<dyn Error>> {
|
||||||
// Error conditions. If the args don't match the length and types of the argdefs then this is
|
// Error conditions. If the args don't match the length and types of the argdefs then this is
|
||||||
// macro call error.
|
// func call error.
|
||||||
if args.len() > self.argdefs.len() {
|
if args.len() > self.argdefs.len() {
|
||||||
return Err(Box::new(error::BuildError::new(
|
return Err(Box::new(error::BuildError::new(
|
||||||
format!(
|
format!(
|
||||||
"Macro called with too many args in file: {}",
|
"Func called with too many args in file: {}",
|
||||||
root.to_string_lossy()
|
root.to_string_lossy()
|
||||||
),
|
),
|
||||||
error::ErrorType::BadArgLen,
|
error::ErrorType::BadArgLen,
|
||||||
@ -71,7 +71,7 @@ impl MacroDef {
|
|||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
// If the args don't match the types required by the expressions then that is a TypeFail.
|
// If the args don't match the types required by the expressions then that is a TypeFail.
|
||||||
// If the expressions reference Symbols not defined in the MacroDef that is also an error.
|
// If the expressions reference Symbols not defined in the FuncDef that is also an error.
|
||||||
let mut build_output = HashMap::<PositionedItem<String>, Rc<Val>>::new();
|
let mut build_output = HashMap::<PositionedItem<String>, Rc<Val>>::new();
|
||||||
for (i, arg) in args.drain(0..).enumerate() {
|
for (i, arg) in args.drain(0..).enumerate() {
|
||||||
build_output
|
build_output
|
||||||
@ -101,10 +101,7 @@ pub struct AssertCollector {
|
|||||||
|
|
||||||
/// Builder handles building ucg code for a single file.
|
/// Builder handles building ucg code for a single file.
|
||||||
pub struct FileBuilder<'a> {
|
pub struct FileBuilder<'a> {
|
||||||
// FIXME(jwall): This should probably become a working directory instead.
|
|
||||||
working_dir: PathBuf,
|
working_dir: PathBuf,
|
||||||
// FIXME(jwall): All of the below is build context shared amongst
|
|
||||||
// various builders.
|
|
||||||
std: Rc<HashMap<String, &'static str>>,
|
std: Rc<HashMap<String, &'static str>>,
|
||||||
import_path: &'a Vec<PathBuf>,
|
import_path: &'a Vec<PathBuf>,
|
||||||
validate_mode: bool,
|
validate_mode: bool,
|
||||||
@ -354,8 +351,8 @@ impl<'a> FileBuilder<'a> {
|
|||||||
|
|
||||||
fn check_reserved_word(name: &str) -> bool {
|
fn check_reserved_word(name: &str) -> bool {
|
||||||
match name {
|
match name {
|
||||||
"self" | "assert" | "true" | "false" | "let" | "import" | "as" | "select" | "macro"
|
"self" | "assert" | "true" | "false" | "let" | "import" | "as" | "select" | "func"
|
||||||
| "module" | "env" | "map" | "filter" | "NULL" | "out" | "in" | "is" => true,
|
| "module" | "env" | "map" | "filter" | "NULL" | "out" | "in" | "is" | "not" => true,
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1171,26 +1168,26 @@ impl<'a> FileBuilder<'a> {
|
|||||||
|
|
||||||
fn eval_call(&self, def: &CallDef, scope: &Scope) -> Result<Rc<Val>, Box<dyn Error>> {
|
fn eval_call(&self, def: &CallDef, scope: &Scope) -> Result<Rc<Val>, Box<dyn Error>> {
|
||||||
let args = &def.arglist;
|
let args = &def.arglist;
|
||||||
let v = self.eval_value(&def.macroref, scope)?;
|
let v = self.eval_value(&def.funcref, scope)?;
|
||||||
if let &Val::Macro(ref m) = v.deref() {
|
if let &Val::Func(ref def) = v.deref() {
|
||||||
// Congratulations this is actually a macro.
|
// Congratulations this is actually a function.
|
||||||
let mut argvals: Vec<Rc<Val>> = Vec::new();
|
let mut argvals: Vec<Rc<Val>> = Vec::new();
|
||||||
for arg in args.iter() {
|
for arg in args.iter() {
|
||||||
argvals.push(self.eval_expr(arg, scope)?);
|
argvals.push(self.eval_expr(arg, scope)?);
|
||||||
}
|
}
|
||||||
return Ok(m.eval(self.working_dir.clone(), self, argvals)?);
|
return Ok(def.eval(self.working_dir.clone(), self, argvals)?);
|
||||||
}
|
}
|
||||||
Err(Box::new(error::BuildError::new(
|
Err(Box::new(error::BuildError::new(
|
||||||
// We should pretty print the selectors here.
|
// We should pretty print the selectors here.
|
||||||
format!("{} is not a Macro", v),
|
format!("{} is not a Function", v),
|
||||||
error::ErrorType::TypeFail,
|
error::ErrorType::TypeFail,
|
||||||
def.pos.clone(),
|
def.pos.clone(),
|
||||||
)))
|
)))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn eval_macro_def(&self, def: &mut MacroDef, scope: &Scope) -> Result<Rc<Val>, Box<dyn Error>> {
|
fn eval_func_def(&self, def: &mut FuncDef, scope: &Scope) -> Result<Rc<Val>, Box<dyn Error>> {
|
||||||
def.scope = Some(scope.spawn_child());
|
def.scope = Some(scope.spawn_child());
|
||||||
Ok(Rc::new(Val::Macro(def.clone())))
|
Ok(Rc::new(Val::Func(def.clone())))
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(jwall): This stays with the FileBuilder specifically.
|
// TODO(jwall): This stays with the FileBuilder specifically.
|
||||||
@ -1261,7 +1258,7 @@ impl<'a> FileBuilder<'a> {
|
|||||||
fn eval_functional_list_processing(
|
fn eval_functional_list_processing(
|
||||||
&self,
|
&self,
|
||||||
elems: &Vec<Rc<Val>>,
|
elems: &Vec<Rc<Val>>,
|
||||||
def: &MacroDef,
|
def: &FuncDef,
|
||||||
typ: ProcessingOpType,
|
typ: ProcessingOpType,
|
||||||
) -> Result<Rc<Val>, Box<dyn Error>> {
|
) -> Result<Rc<Val>, Box<dyn Error>> {
|
||||||
let mut out = Vec::new();
|
let mut out = Vec::new();
|
||||||
@ -1290,7 +1287,7 @@ impl<'a> FileBuilder<'a> {
|
|||||||
fn eval_functional_tuple_processing(
|
fn eval_functional_tuple_processing(
|
||||||
&self,
|
&self,
|
||||||
fs: &Vec<(PositionedItem<String>, Rc<Val>)>,
|
fs: &Vec<(PositionedItem<String>, Rc<Val>)>,
|
||||||
def: &MacroDef,
|
def: &FuncDef,
|
||||||
typ: ProcessingOpType,
|
typ: ProcessingOpType,
|
||||||
) -> Result<Rc<Val>, Box<dyn Error>> {
|
) -> Result<Rc<Val>, Box<dyn Error>> {
|
||||||
let mut out = Vec::new();
|
let mut out = Vec::new();
|
||||||
@ -1358,12 +1355,12 @@ impl<'a> FileBuilder<'a> {
|
|||||||
fn eval_reduce_op(&self, def: &ReduceOpDef, scope: &Scope) -> Result<Rc<Val>, Box<dyn Error>> {
|
fn eval_reduce_op(&self, def: &ReduceOpDef, scope: &Scope) -> Result<Rc<Val>, Box<dyn Error>> {
|
||||||
let maybe_target = self.eval_expr(&def.target, scope)?;
|
let maybe_target = self.eval_expr(&def.target, scope)?;
|
||||||
let mut acc = self.eval_expr(&def.acc, scope)?;
|
let mut acc = self.eval_expr(&def.acc, scope)?;
|
||||||
let maybe_mac = self.eval_value(&Value::Symbol(def.mac.clone()), &self.scope.clone())?;
|
let maybe_mac = self.eval_value(&Value::Symbol(def.func.clone()), &self.scope.clone())?;
|
||||||
let macdef = match maybe_mac.as_ref() {
|
let funcdef = match maybe_mac.as_ref() {
|
||||||
&Val::Macro(ref macdef) => macdef,
|
&Val::Func(ref funcdef) => funcdef,
|
||||||
_ => {
|
_ => {
|
||||||
return Err(Box::new(error::BuildError::new(
|
return Err(Box::new(error::BuildError::new(
|
||||||
format!("Expected macro but got {:?}", def.mac),
|
format!("Expected func but got {:?}", def.func),
|
||||||
error::ErrorType::TypeFail,
|
error::ErrorType::TypeFail,
|
||||||
def.pos.clone(),
|
def.pos.clone(),
|
||||||
)));
|
)));
|
||||||
@ -1373,7 +1370,7 @@ impl<'a> FileBuilder<'a> {
|
|||||||
&Val::List(ref elems) => {
|
&Val::List(ref elems) => {
|
||||||
for item in elems.iter() {
|
for item in elems.iter() {
|
||||||
let argvals = vec![acc.clone(), item.clone()];
|
let argvals = vec![acc.clone(), item.clone()];
|
||||||
let result = macdef.eval(self.working_dir.clone(), self, argvals)?;
|
let result = funcdef.eval(self.working_dir.clone(), self, argvals)?;
|
||||||
acc = result;
|
acc = result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1384,14 +1381,14 @@ impl<'a> FileBuilder<'a> {
|
|||||||
Rc::new(Val::Str(name.val.clone())),
|
Rc::new(Val::Str(name.val.clone())),
|
||||||
val.clone(),
|
val.clone(),
|
||||||
];
|
];
|
||||||
let result = macdef.eval(self.working_dir.clone(), self, argvals)?;
|
let result = funcdef.eval(self.working_dir.clone(), self, argvals)?;
|
||||||
acc = result;
|
acc = result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
&Val::Str(ref s) => {
|
&Val::Str(ref s) => {
|
||||||
for gc in s.graphemes(true) {
|
for gc in s.graphemes(true) {
|
||||||
let argvals = vec![acc.clone(), Rc::new(Val::Str(gc.to_string()))];
|
let argvals = vec![acc.clone(), Rc::new(Val::Str(gc.to_string()))];
|
||||||
let result = macdef.eval(self.working_dir.clone(), self, argvals)?;
|
let result = funcdef.eval(self.working_dir.clone(), self, argvals)?;
|
||||||
acc = result;
|
acc = result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1412,7 +1409,7 @@ impl<'a> FileBuilder<'a> {
|
|||||||
fn eval_functional_string_processing(
|
fn eval_functional_string_processing(
|
||||||
&self,
|
&self,
|
||||||
s: &str,
|
s: &str,
|
||||||
def: &MacroDef,
|
def: &FuncDef,
|
||||||
typ: ProcessingOpType,
|
typ: ProcessingOpType,
|
||||||
) -> Result<Rc<Val>, Box<dyn Error>> {
|
) -> Result<Rc<Val>, Box<dyn Error>> {
|
||||||
let mut result = String::new();
|
let mut result = String::new();
|
||||||
@ -1466,12 +1463,12 @@ impl<'a> FileBuilder<'a> {
|
|||||||
scope: &Scope,
|
scope: &Scope,
|
||||||
) -> Result<Rc<Val>, Box<dyn Error>> {
|
) -> Result<Rc<Val>, Box<dyn Error>> {
|
||||||
let maybe_target = self.eval_expr(&def.target, scope)?;
|
let maybe_target = self.eval_expr(&def.target, scope)?;
|
||||||
let maybe_mac = self.eval_value(&Value::Symbol(def.mac.clone()), &self.scope.clone())?;
|
let maybe_mac = self.eval_value(&Value::Symbol(def.func.clone()), &self.scope.clone())?;
|
||||||
let macdef = match maybe_mac.as_ref() {
|
let macdef = match maybe_mac.as_ref() {
|
||||||
&Val::Macro(ref macdef) => macdef,
|
&Val::Func(ref macdef) => macdef,
|
||||||
_ => {
|
_ => {
|
||||||
return Err(Box::new(error::BuildError::new(
|
return Err(Box::new(error::BuildError::new(
|
||||||
format!("Expected macro but got {:?}", def.mac),
|
format!("Expected func but got {:?}", def.func),
|
||||||
error::ErrorType::TypeFail,
|
error::ErrorType::TypeFail,
|
||||||
def.pos.clone(),
|
def.pos.clone(),
|
||||||
)));
|
)));
|
||||||
@ -1578,7 +1575,7 @@ impl<'a> FileBuilder<'a> {
|
|||||||
| &Val::Int(_)
|
| &Val::Int(_)
|
||||||
| &Val::Str(_)
|
| &Val::Str(_)
|
||||||
| &Val::List(_)
|
| &Val::List(_)
|
||||||
| &Val::Macro(_)
|
| &Val::Func(_)
|
||||||
| &Val::Module(_) => {
|
| &Val::Module(_) => {
|
||||||
// record an assertion type-failure result.
|
// record an assertion type-failure result.
|
||||||
let msg = format!(
|
let msg = format!(
|
||||||
@ -1737,7 +1734,7 @@ impl<'a> FileBuilder<'a> {
|
|||||||
"float" => val.is_float(),
|
"float" => val.is_float(),
|
||||||
"tuple" => val.is_tuple(),
|
"tuple" => val.is_tuple(),
|
||||||
"list" => val.is_list(),
|
"list" => val.is_list(),
|
||||||
"macro" => val.is_macro(),
|
"func" => val.is_func(),
|
||||||
"module" => val.is_module(),
|
"module" => val.is_module(),
|
||||||
other => {
|
other => {
|
||||||
return Err(Box::new(error::BuildError::new(
|
return Err(Box::new(error::BuildError::new(
|
||||||
@ -1761,9 +1758,9 @@ impl<'a> FileBuilder<'a> {
|
|||||||
&Expression::Grouped(ref expr) => self.eval_expr(expr, scope),
|
&Expression::Grouped(ref expr) => self.eval_expr(expr, scope),
|
||||||
&Expression::Format(ref def) => self.eval_format(def, scope),
|
&Expression::Format(ref def) => self.eval_format(def, scope),
|
||||||
&Expression::Call(ref def) => self.eval_call(def, scope),
|
&Expression::Call(ref def) => self.eval_call(def, scope),
|
||||||
&Expression::Macro(ref def) => {
|
&Expression::Func(ref def) => {
|
||||||
let mut def_clone = def.clone();
|
let mut def_clone = def.clone();
|
||||||
self.eval_macro_def(&mut def_clone, scope)
|
self.eval_func_def(&mut def_clone, scope)
|
||||||
}
|
}
|
||||||
&Expression::Module(ref def) => {
|
&Expression::Module(ref def) => {
|
||||||
let mut def_clone = def.clone();
|
let mut def_clone = def.clone();
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
use super::assets::MemoryCache;
|
use super::assets::MemoryCache;
|
||||||
use super::{CallDef, FileBuilder, MacroDef, SelectDef, Val};
|
use super::{FileBuilder, SelectDef, Val};
|
||||||
use crate::ast::*;
|
use crate::ast::*;
|
||||||
|
|
||||||
use std;
|
use std;
|
||||||
@ -234,50 +234,6 @@ fn test_expr_copy_field_type_error() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
#[should_panic(expected = "Unable to find binding arg1")]
|
|
||||||
fn test_macro_hermetic() {
|
|
||||||
let i_paths = Vec::new();
|
|
||||||
let cache = Rc::new(RefCell::new(MemoryCache::new()));
|
|
||||||
let mut b = FileBuilder::new(std::env::current_dir().unwrap(), &i_paths, cache);
|
|
||||||
b.scope
|
|
||||||
.build_output
|
|
||||||
.entry(value_node!("arg1".to_string(), Position::new(1, 0, 0)))
|
|
||||||
.or_insert(Rc::new(Val::Str("bar".to_string())));
|
|
||||||
b.scope
|
|
||||||
.build_output
|
|
||||||
.entry(value_node!("tstmac".to_string(), Position::new(1, 0, 0)))
|
|
||||||
.or_insert(Rc::new(Val::Macro(MacroDef {
|
|
||||||
scope: None,
|
|
||||||
argdefs: vec![value_node!("arg2".to_string(), Position::new(1, 0, 0))],
|
|
||||||
fields: Box::new(Expression::Simple(Value::Symbol(value_node!(
|
|
||||||
"arg1".to_string(),
|
|
||||||
Position::new(1, 1, 1)
|
|
||||||
)))),
|
|
||||||
pos: Position::new(1, 0, 0),
|
|
||||||
})));
|
|
||||||
test_expr_to_val(
|
|
||||||
vec![(
|
|
||||||
Expression::Call(CallDef {
|
|
||||||
macroref: Value::Symbol(PositionedItem::new(
|
|
||||||
"tstmac".to_string(),
|
|
||||||
Position::new(1, 1, 1),
|
|
||||||
)),
|
|
||||||
arglist: vec![Expression::Simple(Value::Str(value_node!(
|
|
||||||
"bar".to_string(),
|
|
||||||
Position::new(1, 1, 1)
|
|
||||||
)))],
|
|
||||||
pos: Position::new(1, 1, 1),
|
|
||||||
}),
|
|
||||||
Val::Tuple(vec![(
|
|
||||||
value_node!("foo".to_string(), Position::new(1, 1, 1)),
|
|
||||||
Rc::new(Val::Str("bar".to_string())),
|
|
||||||
)]),
|
|
||||||
)],
|
|
||||||
b,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[should_panic(expected = "Expected String but got Integer in Select expression")]
|
#[should_panic(expected = "Expected String but got Integer in Select expression")]
|
||||||
fn test_select_expr_not_a_string() {
|
fn test_select_expr_not_a_string() {
|
||||||
|
@ -78,9 +78,9 @@ impl EnvConverter {
|
|||||||
&Val::Tuple(ref flds) => {
|
&Val::Tuple(ref flds) => {
|
||||||
self.convert_tuple(flds, w)?;
|
self.convert_tuple(flds, w)?;
|
||||||
}
|
}
|
||||||
&Val::Macro(ref _def) => {
|
&Val::Func(ref _def) => {
|
||||||
// This is ignored
|
// This is ignored
|
||||||
eprintln!("Skipping macro...");
|
eprintln!("Skipping func...");
|
||||||
}
|
}
|
||||||
&Val::Env(ref _fs) => {
|
&Val::Env(ref _fs) => {
|
||||||
// This is ignored
|
// This is ignored
|
||||||
|
@ -41,7 +41,7 @@ impl FlagConverter {
|
|||||||
// first of all we need to make sure that each &Val is only a primitive type.
|
// first of all we need to make sure that each &Val is only a primitive type.
|
||||||
for v in def.iter() {
|
for v in def.iter() {
|
||||||
let vref = v.as_ref();
|
let vref = v.as_ref();
|
||||||
if vref.is_list() || vref.is_tuple() || vref.is_macro() {
|
if vref.is_list() || vref.is_tuple() || vref.is_func() {
|
||||||
eprintln!(
|
eprintln!(
|
||||||
"Skipping non primitive val in list for flag {}{}",
|
"Skipping non primitive val in list for flag {}{}",
|
||||||
pfx, name
|
pfx, name
|
||||||
@ -96,7 +96,7 @@ impl FlagConverter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
&Val::Macro(ref _def) => {
|
&Val::Func(ref _def) => {
|
||||||
// This is ignored
|
// This is ignored
|
||||||
eprintln!("Skipping macro...");
|
eprintln!("Skipping macro...");
|
||||||
}
|
}
|
||||||
|
@ -75,8 +75,8 @@ impl JsonConverter {
|
|||||||
serde_json::Value::Number(n)
|
serde_json::Value::Number(n)
|
||||||
}
|
}
|
||||||
&Val::Str(ref s) => serde_json::Value::String(s.clone()),
|
&Val::Str(ref s) => serde_json::Value::String(s.clone()),
|
||||||
&Val::Macro(_) => {
|
&Val::Func(_) => {
|
||||||
eprintln!("Skipping macro encoding as null...");
|
eprintln!("Skipping func encoding as null...");
|
||||||
serde_json::Value::Null
|
serde_json::Value::Null
|
||||||
}
|
}
|
||||||
&Val::Module(_) => {
|
&Val::Module(_) => {
|
||||||
|
@ -69,8 +69,8 @@ impl TomlConverter {
|
|||||||
&Val::Float(f) => toml::Value::Float(f),
|
&Val::Float(f) => toml::Value::Float(f),
|
||||||
&Val::Int(i) => toml::Value::Integer(i),
|
&Val::Int(i) => toml::Value::Integer(i),
|
||||||
&Val::Str(ref s) => toml::Value::String(s.clone()),
|
&Val::Str(ref s) => toml::Value::String(s.clone()),
|
||||||
&Val::Macro(_) => {
|
&Val::Func(_) => {
|
||||||
let err = SimpleError::new("Macros are not allowed in Toml Conversions!");
|
let err = SimpleError::new("Functions are not allowed in Toml Conversions!");
|
||||||
return Err(Box::new(err));
|
return Err(Box::new(err));
|
||||||
}
|
}
|
||||||
&Val::Module(_) => {
|
&Val::Module(_) => {
|
||||||
|
@ -61,8 +61,8 @@ impl YamlConverter {
|
|||||||
_ => panic!("Int is too large or not a Number {}", i),
|
_ => panic!("Int is too large or not a Number {}", i),
|
||||||
},
|
},
|
||||||
&Val::Str(ref s) => serde_yaml::Value::String(s.clone()),
|
&Val::Str(ref s) => serde_yaml::Value::String(s.clone()),
|
||||||
&Val::Macro(_) => {
|
&Val::Func(_) => {
|
||||||
eprintln!("Skipping macro encoding as null...");
|
eprintln!("Skipping func encoding as null...");
|
||||||
serde_yaml::Value::Null
|
serde_yaml::Value::Null
|
||||||
}
|
}
|
||||||
&Val::Module(_) => {
|
&Val::Module(_) => {
|
||||||
|
@ -341,7 +341,7 @@ make_fn!(
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
fn tuple_to_macro<'a>(
|
fn tuple_to_func<'a>(
|
||||||
pos: Position,
|
pos: Position,
|
||||||
vals: Option<Vec<Value>>,
|
vals: Option<Vec<Value>>,
|
||||||
val: Expression,
|
val: Expression,
|
||||||
@ -357,7 +357,7 @@ fn tuple_to_macro<'a>(
|
|||||||
val: s.to_string(),
|
val: s.to_string(),
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
Ok(Expression::Macro(MacroDef {
|
Ok(Expression::Func(FuncDef {
|
||||||
scope: None,
|
scope: None,
|
||||||
argdefs: arglist,
|
argdefs: arglist,
|
||||||
fields: Box::new(val),
|
fields: Box::new(val),
|
||||||
@ -401,10 +401,10 @@ fn module_expression(input: SliceIter<Token>) -> Result<SliceIter<Token>, Expres
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn macro_expression(input: SliceIter<Token>) -> Result<SliceIter<Token>, Expression> {
|
fn func_expression(input: SliceIter<Token>) -> Result<SliceIter<Token>, Expression> {
|
||||||
let parsed = do_each!(input,
|
let parsed = do_each!(input,
|
||||||
pos => pos,
|
pos => pos,
|
||||||
_ => word!("macro"),
|
_ => word!("func"),
|
||||||
_ => must!(punct!("(")),
|
_ => must!(punct!("(")),
|
||||||
arglist => trace_parse!(optional!(arglist)),
|
arglist => trace_parse!(optional!(arglist)),
|
||||||
_ => must!(punct!(")")),
|
_ => must!(punct!(")")),
|
||||||
@ -416,10 +416,10 @@ fn macro_expression(input: SliceIter<Token>) -> Result<SliceIter<Token>, Express
|
|||||||
Result::Abort(e) => Result::Abort(e),
|
Result::Abort(e) => Result::Abort(e),
|
||||||
Result::Fail(e) => Result::Fail(e),
|
Result::Fail(e) => Result::Fail(e),
|
||||||
Result::Incomplete(offset) => Result::Incomplete(offset),
|
Result::Incomplete(offset) => Result::Incomplete(offset),
|
||||||
Result::Complete(rest, (pos, arglist, map)) => match tuple_to_macro(pos, arglist, map) {
|
Result::Complete(rest, (pos, arglist, map)) => match tuple_to_func(pos, arglist, map) {
|
||||||
Ok(expr) => Result::Complete(rest, expr),
|
Ok(expr) => Result::Complete(rest, expr),
|
||||||
Err(e) => Result::Fail(Error::caused_by(
|
Err(e) => Result::Fail(Error::caused_by(
|
||||||
"Invalid Macro syntax",
|
"Invalid func syntax",
|
||||||
Box::new(e),
|
Box::new(e),
|
||||||
Box::new(rest.clone()),
|
Box::new(rest.clone()),
|
||||||
)),
|
)),
|
||||||
@ -522,7 +522,7 @@ fn tuple_to_call<'a>(
|
|||||||
) -> ConvertResult<'a, Expression> {
|
) -> ConvertResult<'a, Expression> {
|
||||||
if let Value::Symbol(_) = val {
|
if let Value::Symbol(_) = val {
|
||||||
Ok(Expression::Call(CallDef {
|
Ok(Expression::Call(CallDef {
|
||||||
macroref: val,
|
funcref: val,
|
||||||
arglist: exprs.unwrap_or_else(|| Vec::new()),
|
arglist: exprs.unwrap_or_else(|| Vec::new()),
|
||||||
pos: (&input).into(),
|
pos: (&input).into(),
|
||||||
}))
|
}))
|
||||||
@ -562,12 +562,12 @@ make_fn!(
|
|||||||
do_each!(
|
do_each!(
|
||||||
pos => pos,
|
pos => pos,
|
||||||
_ => word!("reduce"),
|
_ => word!("reduce"),
|
||||||
macroname => must!(match_type!(BAREWORD)),
|
funcname => must!(match_type!(BAREWORD)),
|
||||||
acc => must!(trace_parse!(non_op_expression)),
|
acc => must!(trace_parse!(non_op_expression)),
|
||||||
_ => must!(punct!(",")),
|
_ => must!(punct!(",")),
|
||||||
tgt => must!(trace_parse!(non_op_expression)),
|
tgt => must!(trace_parse!(non_op_expression)),
|
||||||
(Expression::FuncOp(FuncOpDef::Reduce(ReduceOpDef{
|
(Expression::FuncOp(FuncOpDef::Reduce(ReduceOpDef{
|
||||||
mac: (¯oname).into(),
|
func: (&funcname).into(),
|
||||||
acc: Box::new(acc),
|
acc: Box::new(acc),
|
||||||
target: Box::new(tgt),
|
target: Box::new(tgt),
|
||||||
pos: pos,
|
pos: pos,
|
||||||
@ -580,10 +580,10 @@ make_fn!(
|
|||||||
do_each!(
|
do_each!(
|
||||||
pos => pos,
|
pos => pos,
|
||||||
_ => word!("map"),
|
_ => word!("map"),
|
||||||
macroname => must!(match_type!(BAREWORD)),
|
funcname => must!(match_type!(BAREWORD)),
|
||||||
list => must!(trace_parse!(non_op_expression)),
|
list => must!(trace_parse!(non_op_expression)),
|
||||||
(Expression::FuncOp(FuncOpDef::Map(MapFilterOpDef{
|
(Expression::FuncOp(FuncOpDef::Map(MapFilterOpDef{
|
||||||
mac: (¯oname).into(),
|
func: (&funcname).into(),
|
||||||
target: Box::new(list),
|
target: Box::new(list),
|
||||||
pos: pos,
|
pos: pos,
|
||||||
})))
|
})))
|
||||||
@ -595,10 +595,10 @@ make_fn!(
|
|||||||
do_each!(
|
do_each!(
|
||||||
pos => pos,
|
pos => pos,
|
||||||
_ => word!("filter"),
|
_ => word!("filter"),
|
||||||
macroname => must!(match_type!(BAREWORD)),
|
funcname => must!(match_type!(BAREWORD)),
|
||||||
list => must!(trace_parse!(non_op_expression)),
|
list => must!(trace_parse!(non_op_expression)),
|
||||||
(Expression::FuncOp(FuncOpDef::Filter(MapFilterOpDef{
|
(Expression::FuncOp(FuncOpDef::Filter(MapFilterOpDef{
|
||||||
mac: (¯oname).into(),
|
func: (&funcname).into(),
|
||||||
target: Box::new(list),
|
target: Box::new(list),
|
||||||
pos: pos,
|
pos: pos,
|
||||||
})))
|
})))
|
||||||
@ -696,7 +696,7 @@ make_fn!(
|
|||||||
non_op_expression<SliceIter<Token>, Expression>,
|
non_op_expression<SliceIter<Token>, Expression>,
|
||||||
either!(
|
either!(
|
||||||
trace_parse!(func_op_expression),
|
trace_parse!(func_op_expression),
|
||||||
trace_parse!(macro_expression),
|
trace_parse!(func_expression),
|
||||||
trace_parse!(import_expression),
|
trace_parse!(import_expression),
|
||||||
trace_parse!(not_expression),
|
trace_parse!(not_expression),
|
||||||
trace_parse!(fail_expression),
|
trace_parse!(fail_expression),
|
||||||
|
@ -286,8 +286,8 @@ make_fn!(failtok<OffsetStrIter, Token>,
|
|||||||
do_text_token_tok!(TokenType::BAREWORD, "fail", WS)
|
do_text_token_tok!(TokenType::BAREWORD, "fail", WS)
|
||||||
);
|
);
|
||||||
|
|
||||||
make_fn!(macrotok<OffsetStrIter, Token>,
|
make_fn!(functok<OffsetStrIter, Token>,
|
||||||
do_text_token_tok!(TokenType::BAREWORD, "macro", WS)
|
do_text_token_tok!(TokenType::BAREWORD, "func", WS)
|
||||||
);
|
);
|
||||||
|
|
||||||
make_fn!(moduletok<OffsetStrIter, Token>,
|
make_fn!(moduletok<OffsetStrIter, Token>,
|
||||||
@ -427,7 +427,7 @@ fn token<'a>(input: OffsetStrIter<'a>) -> Result<OffsetStrIter<'a>, Token> {
|
|||||||
selecttok,
|
selecttok,
|
||||||
asserttok,
|
asserttok,
|
||||||
failtok,
|
failtok,
|
||||||
macrotok,
|
functok,
|
||||||
moduletok,
|
moduletok,
|
||||||
importtok,
|
importtok,
|
||||||
includetok,
|
includetok,
|
||||||
|
@ -154,7 +154,7 @@ fn test_lteqtok() {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_tokenize_one_of_each() {
|
fn test_tokenize_one_of_each() {
|
||||||
let input = OffsetStrIter::new(
|
let input = OffsetStrIter::new(
|
||||||
"map out filter assert let import macro select as => [ ] { } ; = % / * \
|
"map out filter assert let import func select as => [ ] { } ; = % / * \
|
||||||
+ - . ( ) , 1 . foo \"bar\" // comment\n ; true false == < > <= >= !=",
|
+ - . ( ) , 1 . foo \"bar\" // comment\n ; true false == < > <= >= !=",
|
||||||
);
|
);
|
||||||
let result = tokenize(input.clone());
|
let result = tokenize(input.clone());
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
let maybe = module{
|
let maybe = module{
|
||||||
val = NULL,
|
val = NULL,
|
||||||
} => {
|
} => {
|
||||||
let do = macro(op) => select (mod.val != NULL), NULL, {
|
let do = func (op) => select (mod.val != NULL), NULL, {
|
||||||
true = op(mod.val),
|
true = op(mod.val),
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@ -9,9 +9,9 @@ let maybe = module{
|
|||||||
let if = module{
|
let if = module{
|
||||||
test = false,
|
test = false,
|
||||||
} => {
|
} => {
|
||||||
let do = macro(op, arg) => select mod.test, arg, {
|
let do = func (op, arg) => select mod.test, arg, {
|
||||||
true = op(arg),
|
true = op(arg),
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
let identity = macro(arg) => arg;
|
let identity = func (arg) => arg;
|
@ -2,7 +2,7 @@ let str_join = module{
|
|||||||
sep=" ",
|
sep=" ",
|
||||||
list=NULL,
|
list=NULL,
|
||||||
} => {
|
} => {
|
||||||
let joiner = macro(acc, item) => select (acc.out == ""), NULL, {
|
let joiner = func (acc, item) => select (acc.out == ""), NULL, {
|
||||||
true = acc{
|
true = acc{
|
||||||
out="@@" % (acc.out,item),
|
out="@@" % (acc.out,item),
|
||||||
},
|
},
|
||||||
@ -17,7 +17,7 @@ let str_join = module{
|
|||||||
let len = module{
|
let len = module{
|
||||||
list = NULL,
|
list = NULL,
|
||||||
} => {
|
} => {
|
||||||
let counter = macro(acc, item) => acc + 1;
|
let counter = func (acc, item) => acc + 1;
|
||||||
|
|
||||||
let result = reduce counter 0, (mod.list);
|
let result = reduce counter 0, (mod.list);
|
||||||
};
|
};
|
||||||
@ -25,7 +25,7 @@ let len = module{
|
|||||||
let reverse = module{
|
let reverse = module{
|
||||||
list = NULL,
|
list = NULL,
|
||||||
} => {
|
} => {
|
||||||
let reducer = macro(acc, item) => [item] + acc;
|
let reducer = func (acc, item) => [item] + acc;
|
||||||
|
|
||||||
let result = reduce reducer [], (mod.list);
|
let result = reduce reducer [], (mod.list);
|
||||||
};
|
};
|
||||||
@ -35,7 +35,7 @@ let enumerate = module{
|
|||||||
step = 1,
|
step = 1,
|
||||||
list = NULL,
|
list = NULL,
|
||||||
} => {
|
} => {
|
||||||
let reducer = macro(acc, item) => acc{
|
let reducer = func (acc, item) => acc{
|
||||||
count = acc.count + acc.step,
|
count = acc.count + acc.step,
|
||||||
list=acc.list + [[acc.count, item]],
|
list=acc.list + [[acc.count, item]],
|
||||||
};
|
};
|
||||||
@ -50,7 +50,7 @@ let zip = module{
|
|||||||
list1 = NULL,
|
list1 = NULL,
|
||||||
list2 = NULL,
|
list2 = NULL,
|
||||||
} => {
|
} => {
|
||||||
let counter = macro(acc, item) => acc + 1;
|
let counter = func (acc, item) => acc + 1;
|
||||||
|
|
||||||
let len1 = reduce counter 0, (mod.list1);
|
let len1 = reduce counter 0, (mod.list1);
|
||||||
let len2 = reduce counter 0, (mod.list2);
|
let len2 = reduce counter 0, (mod.list2);
|
||||||
@ -60,7 +60,7 @@ let zip = module{
|
|||||||
false = 0:(len2 - 1),
|
false = 0:(len2 - 1),
|
||||||
};
|
};
|
||||||
|
|
||||||
let reducer = macro(acc, item) => acc{
|
let reducer = func (acc, item) => acc{
|
||||||
result = acc.result + [[acc.list1.(item), acc.list2.(item)]],
|
result = acc.result + [[acc.list1.(item), acc.list2.(item)]],
|
||||||
idxs = acc.idxs + [item]
|
idxs = acc.idxs + [item]
|
||||||
};
|
};
|
||||||
|
@ -7,21 +7,21 @@ let base_types = [
|
|||||||
"null",
|
"null",
|
||||||
"tuple",
|
"tuple",
|
||||||
"list",
|
"list",
|
||||||
"macro",
|
"func",
|
||||||
"module",
|
"module",
|
||||||
];
|
];
|
||||||
|
|
||||||
let base_type_reducer = macro(acc, f) => select (acc.val is f), f, {
|
let base_type_reducer = func (acc, f) => select (acc.val is f), f, {
|
||||||
true = acc{typ = f},
|
true = acc{typ = f},
|
||||||
false = acc,
|
false = acc,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Computes the base type of a value.
|
// Computes the base type of a value.
|
||||||
let base_type_of = macro(val) => (reduce base_type_reducer {val=val, typ="null"}, base_types).typ;
|
let base_type_of = func (val) => (reduce base_type_reducer {val=val, typ="null"}, base_types).typ;
|
||||||
|
|
||||||
// Turns any schema check module into a compile failure.
|
// Turns any schema check module into a compile failure.
|
||||||
// The module must export the computed value as the result field.
|
// The module must export the computed value as the result field.
|
||||||
let must = macro(m, msg) => select m.result, fail msg, {
|
let must = func (m, msg) => select m.result, fail msg, {
|
||||||
true = m.result,
|
true = m.result,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -36,10 +36,10 @@ let any = module {
|
|||||||
} => {
|
} => {
|
||||||
let schema = import "std/schema.ucg";
|
let schema = import "std/schema.ucg";
|
||||||
|
|
||||||
let reducer = macro(acc, t) => acc{
|
let reducer = func (acc, t) => acc{
|
||||||
ok = acc.ok || (schema.shaped{val=acc.val, shape=t}.result),
|
ok = acc.ok || (schema.shaped{val=acc.val, shape=t}.result),
|
||||||
};
|
};
|
||||||
let any = macro(val, types) => reduce reducer {ok=false, val=val}, types;
|
let any = func (val, types) => reduce reducer {ok=false, val=val}, types;
|
||||||
|
|
||||||
let result = any(mod.val, mod.types).ok;
|
let result = any(mod.val, mod.types).ok;
|
||||||
};
|
};
|
||||||
@ -51,7 +51,7 @@ let any = module {
|
|||||||
// recurse into nested tuples.
|
// recurse into nested tuples.
|
||||||
//
|
//
|
||||||
// Lists are assumed to be able to contain any type and can be any length.
|
// Lists are assumed to be able to contain any type and can be any length.
|
||||||
// We do not check that macros or modules have the same argument lengths or types
|
// We do not check that functions or modules have the same argument lengths or types
|
||||||
// nor we check that they output the same types.
|
// nor we check that they output the same types.
|
||||||
let shaped = module {
|
let shaped = module {
|
||||||
// The source value to validate
|
// The source value to validate
|
||||||
@ -68,9 +68,9 @@ let shaped = module {
|
|||||||
} => {
|
} => {
|
||||||
let schema = import "std/schema.ucg";
|
let schema = import "std/schema.ucg";
|
||||||
|
|
||||||
let simple_handler = macro(val, shape) => val is (schema.base_type_of(shape));
|
let simple_handler = func (val, shape) => val is (schema.base_type_of(shape));
|
||||||
|
|
||||||
let tuple_handler = macro(acc, name, value) => acc{
|
let tuple_handler = func (acc, name, value) => acc{
|
||||||
ok = select (name) in acc.shape, mod.partial, {
|
ok = select (name) in acc.shape, mod.partial, {
|
||||||
true = schema.shaped{val=value, shape=acc.shape.(name)}.result,
|
true = schema.shaped{val=value, shape=acc.shape.(name)}.result,
|
||||||
},
|
},
|
||||||
@ -84,7 +84,7 @@ let shaped = module {
|
|||||||
null = simple_handler(mod.val, mod.shape),
|
null = simple_handler(mod.val, mod.shape),
|
||||||
tuple = (reduce tuple_handler {shape=mod.shape, ok=false}, (mod.val)).ok,
|
tuple = (reduce tuple_handler {shape=mod.shape, ok=false}, (mod.val)).ok,
|
||||||
list = simple_handler(mod.val, mod.shape),
|
list = simple_handler(mod.val, mod.shape),
|
||||||
macro = simple_handler(mod.val, mod.shape),
|
func = simple_handler(mod.val, mod.shape),
|
||||||
module = simple_handler(mod.val, mod.shape),
|
module = simple_handler(mod.val, mod.shape),
|
||||||
};
|
};
|
||||||
};
|
};
|
@ -1,7 +1,7 @@
|
|||||||
let t = (import "std/testing.ucg").asserts{};
|
let t = (import "std/testing.ucg").asserts{};
|
||||||
let f = (import "std/functional.ucg");
|
let f = (import "std/functional.ucg");
|
||||||
|
|
||||||
let op = macro(arg) => arg{foo="bar"};
|
let op = func (arg) => arg{foo="bar"};
|
||||||
|
|
||||||
assert t.equal{
|
assert t.equal{
|
||||||
left = f.maybe{val=NULL}.do(op),
|
left = f.maybe{val=NULL}.do(op),
|
||||||
|
@ -52,8 +52,8 @@ assert t.equal{
|
|||||||
};
|
};
|
||||||
|
|
||||||
assert t.equal{
|
assert t.equal{
|
||||||
left = schema.base_type_of(macro(arg) => arg),
|
left = schema.base_type_of(func(arg) => arg),
|
||||||
right = "macro",
|
right = "func",
|
||||||
};
|
};
|
||||||
|
|
||||||
assert t.equal{
|
assert t.equal{
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
let assert_tuple = macro(tpl) => select tpl is "tuple", NULL, {
|
let assert_tuple = func (tpl) => select tpl is "tuple", NULL, {
|
||||||
false = fail "@ is not a tuple" % (tpl),
|
false = fail "@ is not a tuple" % (tpl),
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -10,7 +10,7 @@ let fields = module{
|
|||||||
// First we check that mod.tpl is a tuple.
|
// First we check that mod.tpl is a tuple.
|
||||||
assert_tuple(mod.tpl);
|
assert_tuple(mod.tpl);
|
||||||
|
|
||||||
let reducer = macro(acc, field, value) => acc + [field];
|
let reducer = func (acc, field, value) => acc + [field];
|
||||||
|
|
||||||
let result = reduce reducer [], (mod.tpl);
|
let result = reduce reducer [], (mod.tpl);
|
||||||
};
|
};
|
||||||
@ -23,7 +23,7 @@ let values = module{
|
|||||||
// First we check that mod.tpl is a tuple.
|
// First we check that mod.tpl is a tuple.
|
||||||
assert_tuple(mod.tpl);
|
assert_tuple(mod.tpl);
|
||||||
|
|
||||||
let reducer = macro(acc, field, value) => acc + [value];
|
let reducer = func (acc, field, value) => acc + [value];
|
||||||
|
|
||||||
let result = reduce reducer [], (mod.tpl);
|
let result = reduce reducer [], (mod.tpl);
|
||||||
};
|
};
|
||||||
@ -35,7 +35,7 @@ let iter = module{
|
|||||||
// First we check that mod.tpl is a tuple.
|
// First we check that mod.tpl is a tuple.
|
||||||
assert_tuple(mod.tpl);
|
assert_tuple(mod.tpl);
|
||||||
|
|
||||||
let reducer = macro(acc, field, value) => acc + [[field, value]];
|
let reducer = func (acc, field, value) => acc + [[field, value]];
|
||||||
|
|
||||||
let result = reduce reducer [], (mod.tpl);
|
let result = reduce reducer [], (mod.tpl);
|
||||||
};
|
};
|
||||||
@ -47,7 +47,7 @@ let strip_nulls = module{
|
|||||||
// First we check that mod.tpl is a tuple.
|
// First we check that mod.tpl is a tuple.
|
||||||
assert_tuple(mod.tpl);
|
assert_tuple(mod.tpl);
|
||||||
|
|
||||||
let filterer = macro(name, value) => value != NULL;
|
let filterer = func (name, value) => value != NULL;
|
||||||
|
|
||||||
let result = filter filterer (mod.tpl);
|
let result = filter filterer (mod.tpl);
|
||||||
};
|
};
|
||||||
@ -62,7 +62,7 @@ let has_fields = module{
|
|||||||
|
|
||||||
let fs = lib.fields{tpl=mod.tpl}.result;
|
let fs = lib.fields{tpl=mod.tpl}.result;
|
||||||
|
|
||||||
let reducer = macro(acc, f) => acc && (f in fs);
|
let reducer = func (acc, f) => acc && (f in fs);
|
||||||
|
|
||||||
let result = reduce reducer true, (mod.fields);
|
let result = reduce reducer true, (mod.fields);
|
||||||
};
|
};
|
||||||
@ -90,7 +90,7 @@ let field_type = module{
|
|||||||
|
|
||||||
let it = lib.iter{tpl=mod.tpl}.result;
|
let it = lib.iter{tpl=mod.tpl}.result;
|
||||||
|
|
||||||
let reducer = macro(acc, l) => acc && (select l.0 == mod.field, NULL, {
|
let reducer = func (acc, l) => acc && (select l.0 == mod.field, NULL, {
|
||||||
true = l.1 is mod.type, // if this is the field then we propagate if it's the right type.
|
true = l.1 is mod.type, // if this is the field then we propagate if it's the right type.
|
||||||
false = true, // if this isn't the field then we propagate true
|
false = true, // if this isn't the field then we propagate true
|
||||||
});
|
});
|
||||||
|
Loading…
x
Reference in New Issue
Block a user