diff --git a/docsite/ucglib/macros.ucg b/docsite/ucglib/macros.ucg index 29335a9..89d883e 100644 --- a/docsite/ucglib/macros.ucg +++ b/docsite/ucglib/macros.ucg @@ -1,4 +1,4 @@ -let bucketbase = macro(name, project, location) => { +let bucketbase = func (name, project, location) => { name = name, type = "storage.v1.bucket", properties = { @@ -25,16 +25,15 @@ let bucketbase = macro(name, project, location) => { role = "READER", }, ], - }, }; -let bucketSelfLink = macro(bucket) => { +let bucketSelfLink = func (bucket) => { name = "@selfLink" % (bucket), value = "https://console.cloud.google.com/storage/browser/@" % (bucket), }; -let bucketGsLink = macro(bucket) => { +let bucketGsLink = func (bucket) => { name = "@gsLink" % (bucket), value = "gs://@" % (bucket), }; \ No newline at end of file diff --git a/example_errors/errors_test.ucg b/example_errors/errors_test.ucg index a21b862..280a4fe 100644 --- a/example_errors/errors_test.ucg +++ b/example_errors/errors_test.ucg @@ -1,4 +1,4 @@ -assert {macro }; +assert {func }; assert {{ foo = hello world}}; assert {{ foo = "hello world"}; assert {{ = }}; diff --git a/examples/shared.ucg b/examples/shared.ucg index 339550e..316d1a4 100644 --- a/examples/shared.ucg +++ b/examples/shared.ucg @@ -1,6 +1,6 @@ let port = 3306; -let mk_site_config = macro(hostname, port) => { +let mk_site_config = func (hostname, port) => { base_url = "https://@/" % (hostname), port = port, dbs = [], diff --git a/examples/test_json.ucg b/examples/test_json.ucg index 1b0f221..55def9a 100644 --- a/examples/test_json.ucg +++ b/examples/test_json.ucg @@ -6,7 +6,7 @@ let dbhost2 = "db2.prod.net"; let dbname = "testdb"; // Constructor for database connection strings. -let mk_db_conn = macro (host, port, db) => { +let mk_db_conn = func (host, port, db) => { host = host, port = port, db = db, @@ -19,7 +19,7 @@ let db_conn2 = mk_db_conn(dbhost2, shared.port, dbname); // We have two database connections in a list let db_conn_list = [db_conn1, db_conn2]; -let connstr_mapper = macro (item) => { +let connstr_mapper = func (item) => { str = item.conn_string }; diff --git a/examples/test_yaml.ucg b/examples/test_yaml.ucg index c87bc84..4d0e136 100644 --- a/examples/test_yaml.ucg +++ b/examples/test_yaml.ucg @@ -6,7 +6,7 @@ let dbhost2 = "db2.prod.net"; let dbname = "testdb"; // Constructor for database connection strings. -let mk_db_conn = macro (host, port, db) => { +let mk_db_conn = func (host, port, db) => { host = host, port = port, db = db, @@ -19,7 +19,7 @@ let db_conn2 = mk_db_conn(dbhost2, shared.port, dbname); // We have two database connections in a list let db_conn_list = [db_conn1, db_conn2]; -let connstr_mapper = macro (item) => { +let connstr_mapper = func (item) => { str = item.conn_string }; diff --git a/integration_tests/functional_processing_test.ucg b/integration_tests/functional_processing_test.ucg index 01970e8..2ab3151 100644 --- a/integration_tests/functional_processing_test.ucg +++ b/integration_tests/functional_processing_test.ucg @@ -3,14 +3,14 @@ let list1 = [1, 2, 3, 4]; let list2 = ["foo", "bar", "foo", "bar"]; -let mapper = macro(item) => item + 1; -let filtrator = macro(item) => select item, NULL, { +let mapper = func (item) => item + 1; +let filtrator = func (item) => select item, NULL, { 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 { ok = reduce identity_list_reducer [], list1 == list1, @@ -26,7 +26,7 @@ assert { 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 { 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]", }; -let s_mapper = macro(arg) => arg + ","; +let s_mapper = func (arg) => arg + ","; assert { ok = map s_mapper "foo" == "f,o,o,", @@ -77,14 +77,14 @@ let test_tpl = { quux = "baz", }; -let identity_tpl_mapper = macro(name, val) => [name, val]; +let identity_tpl_mapper = func (name, val) => [name, val]; assert { ok = 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"], quux = ["cute", "pygmy"], }; @@ -94,10 +94,10 @@ assert { 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 -let tpl_filter = macro(name, val) => name != "foo"; +let tpl_filter = func (name, val) => name != "foo"; assert { ok = filter identity_tpl_filter test_tpl == test_tpl, @@ -109,14 +109,14 @@ assert { 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 { ok = filter o_str_filter "foobar" == "fbar", 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], vals = self.vals + [val], }; @@ -126,14 +126,14 @@ assert { 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 { ok = reduce str_identity_reducer "", "foo" == "foo", desc = "identity reducer copies string", }; -let char_iter = macro(acc, s) => acc + [s]; +let char_iter = func (acc, s) => acc + [s]; assert { ok = reduce char_iter [], "foo" == ["f", "o", "o"], diff --git a/integration_tests/macros_test.ucg b/integration_tests/macros_test.ucg index c7e0a81..7e9acee 100644 --- a/integration_tests/macros_test.ucg +++ b/integration_tests/macros_test.ucg @@ -1,14 +1,14 @@ -let noargmacro = macro() => { +let noargmacro = func () => { field1 = "value", }; -let simplemacro = macro(arg1, arg2, arg3) => { +let simplemacro = func (arg1, arg2, arg3) => { field1 = arg1, field2 = arg2, field3 = arg3, }; -let cplxmacro = macro(argint, argstr, argfloat) => { +let cplxmacro = func (argint, argstr, argfloat) => { field1 = argint + 1, field2 = argstr + " are here", field3 = argfloat - 1.0, @@ -53,7 +53,7 @@ assert { desc = "cplxresult.boolfield == true", }; -let macro_tpl_arg = macro(tpl) => { +let macro_tpl_arg = func (tpl) => { result = tpl.field, }; @@ -68,7 +68,7 @@ assert { let closed_over = "foo"; -let closure = macro(arg1) => { +let closure = func (arg1) => { result = closed_over + arg1, }; @@ -77,7 +77,7 @@ assert { 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 { ok = concat("foo", "bar") == "foobar", diff --git a/integration_tests/select_expressions_test.ucg b/integration_tests/select_expressions_test.ucg index 0368b76..dae560c 100644 --- a/integration_tests/select_expressions_test.ucg +++ b/integration_tests/select_expressions_test.ucg @@ -20,28 +20,28 @@ assert { desc = "defaultgot == \"OOPS\"", }; -// select inside a macro +// select inside a function -let condmacro = macro(arg) => { +let condfunc = func (arg) => { output = select arg, NULL, { opt1 = "yay", opt2 = "boo", }, }; -let result = condmacro("opt1"); +let result = condfunc("opt1"); assert { - ok = condmacro("opt1") == {output = "yay"}, - desc = "condmacro(\"opt1\") == {output = \"yay\"}", + ok = condfunc("opt1") == {output = "yay"}, + desc = "condfunc(\"opt1\") == {output = \"yay\"}", }; assert { - ok = condmacro("opt2") == {output = "boo"}, - desc = "condmacro(\"opt2\") == {output = \"boo\"}", + ok = condfunc("opt2") == {output = "boo"}, + desc = "condfunc(\"opt2\") == {output = \"boo\"}", }; assert { - ok = condmacro("invalid") == {output = NULL}, - desc = "condmacro(\"invalid\") == {output = NULL}", + ok = condfunc("invalid") == {output = NULL}, + desc = "condfunc(\"invalid\") == {output = NULL}", }; let iflike = select true, "default", { diff --git a/integration_tests/selectors_test.ucg b/integration_tests/selectors_test.ucg index 8341c62..74add9b 100644 --- a/integration_tests/selectors_test.ucg +++ b/integration_tests/selectors_test.ucg @@ -6,7 +6,7 @@ let tuple = { deeplist = ["foo", "bar"], }; -let testmacro = macro(arg) => { +let testfunc = func (arg) => { output = arg, }; @@ -47,12 +47,12 @@ assert { desc = "[\"one\", \"two\", \"three\"].0 == \"one\"", }; -let macro_for_test = macro() => { +let func_for_test = func () => { foo = "bar", }; assert { - ok = macro_for_test().foo == "bar", - desc = "macro_for_test().foo == \"bar\"", + ok = func_for_test().foo == "bar", + desc = "func_for_test().foo == \"bar\"", }; let mymodule = module { foo = "bar" } => { diff --git a/integration_tests/types_test.ucg b/integration_tests/types_test.ucg index c9d18ae..fc7bbb1 100644 --- a/integration_tests/types_test.ucg +++ b/integration_tests/types_test.ucg @@ -31,13 +31,13 @@ assert t.not_ok{ }; assert t.ok{ - test = (macro(arg) => arg) is "macro", - desc = "found a macro", + test = (func(arg) => arg) is "func", + desc = "found a func", }; assert t.not_ok{ - test = (macro(arg) => arg) is "list", - desc = "a macro is not a list", + test = (func(arg) => arg) is "list", + desc = "a func is not a list", }; assert t.ok{ @@ -46,11 +46,11 @@ assert t.ok{ }; assert t.not_ok{ - test = module{} => {} is "macro", - desc = "a module is not a macro", + test = module{} => {} is "func", + 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{ test = foo_check({foo="bar"}), diff --git a/src/ast/mod.rs b/src/ast/mod.rs index bc9819f..469454f 100644 --- a/src/ast/mod.rs +++ b/src/ast/mod.rs @@ -289,7 +289,7 @@ impl Value { /// defined. #[derive(PartialEq, Debug, Clone)] pub struct CallDef { - pub macroref: Value, + pub funcref: Value, pub arglist: Vec, pub pos: Position, } @@ -372,11 +372,11 @@ impl<'a> From<&'a PositionedItem> for PositionedItem { } } -/// 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)] -pub struct MacroDef { +pub struct FuncDef { pub scope: Option, pub argdefs: Vec>, pub fields: Box, @@ -491,7 +491,7 @@ pub enum FuncOpDef { #[derive(Debug, PartialEq, Clone)] pub struct ReduceOpDef { - pub mac: PositionedItem, + pub func: PositionedItem, pub acc: Box, pub target: Box, pub pos: Position, @@ -500,7 +500,7 @@ pub struct ReduceOpDef { /// MapFilterOpDef implements the list operations in the UCG AST. #[derive(Debug, PartialEq, Clone)] pub struct MapFilterOpDef { - pub mac: PositionedItem, + pub func: PositionedItem, pub target: Box, pub pos: Position, } @@ -626,7 +626,7 @@ pub enum Expression { Include(IncludeDef), Import(ImportDef), Call(CallDef), - Macro(MacroDef), + Func(FuncDef), Select(SelectDef), FuncOp(FuncOpDef), Module(ModuleDef), @@ -646,7 +646,7 @@ impl Expression { &Expression::Grouped(ref expr) => expr.pos(), &Expression::Format(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::Select(ref def) => &def.pos, &Expression::FuncOp(ref def) => def.pos(), @@ -685,8 +685,8 @@ impl fmt::Display for Expression { &Expression::Call(_) => { write!(w, "")?; } - &Expression::Macro(_) => { - write!(w, "")?; + &Expression::Func(_) => { + write!(w, "")?; } &Expression::Module(_) => { write!(w, "")?; diff --git a/src/ast/walk.rs b/src/ast/walk.rs index 5dce074..ae1438c 100644 --- a/src/ast/walk.rs +++ b/src/ast/walk.rs @@ -89,7 +89,7 @@ impl<'a> AstWalker<'a> { Expression::Grouped(ref mut 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) => { self.walk_fieldset(&mut def.arg_set); for stmt in def.statements.iter_mut() { diff --git a/src/build/compile_test.rs b/src/build/compile_test.rs index 551872e..313ffa5 100644 --- a/src/build/compile_test.rs +++ b/src/build/compile_test.rs @@ -45,7 +45,7 @@ fn test_comparisons() { } #[test] -fn test_macros() { +fn test_funcs() { assert_build(include_str!("../../integration_tests/macros_test.ucg")); } diff --git a/src/build/ir.rs b/src/build/ir.rs index 8b9e452..36de510 100644 --- a/src/build/ir.rs +++ b/src/build/ir.rs @@ -20,7 +20,7 @@ pub enum Val { List(Vec>), Tuple(Vec<(PositionedItem, Rc)>), Env(Vec<(String, String)>), - Macro(MacroDef), + Func(FuncDef), Module(ModuleDef), } @@ -36,7 +36,7 @@ impl Val { &Val::List(_) => "List".to_string(), &Val::Tuple(_) => "Tuple".to_string(), &Val::Env(_) => "Env".to_string(), - &Val::Macro(_) => "Macro".to_string(), + &Val::Func(_) => "Func".to_string(), &Val::Module(_) => "Module".to_string(), } } @@ -54,7 +54,7 @@ impl Val { &Val::List(_), &Val::Tuple(_), &Val::Env(_), - &Val::Macro(_), + &Val::Func(_), &Val::Module(_) ) } @@ -99,8 +99,8 @@ impl Val { Ok(true) } } - (&Val::Macro(_), &Val::Macro(_)) => Err(error::BuildError::new( - "Macros are not comparable", + (&Val::Func(_), &Val::Func(_)) => Err(error::BuildError::new( + "Func are not comparable", error::ErrorType::TypeFail, pos, )), @@ -185,8 +185,8 @@ impl Val { return false; } - pub fn is_macro(&self) -> bool { - if let &Val::Macro(_) = self { + pub fn is_func(&self) -> bool { + if let &Val::Func(_) = self { return true; } return false; @@ -222,7 +222,7 @@ impl Display for Val { } write!(f, "]") } - &Val::Macro(_) => write!(f, "Macro(..)"), + &Val::Func(_) => write!(f, "Func(..)"), &Val::Module(_) => write!(f, "Module{{..}}"), &Val::Tuple(ref def) => { write!(f, "{{\n")?; diff --git a/src/build/mod.rs b/src/build/mod.rs index 5352fbe..3c8988b 100644 --- a/src/build/mod.rs +++ b/src/build/mod.rs @@ -49,21 +49,21 @@ enum ProcessingOpType { Filter, } -impl MacroDef { - /// Expands a ucg Macro using the given arguments into a new Tuple. +impl FuncDef { + /// Expands a ucg function using the given arguments into a new Tuple. pub fn eval( &self, - // TODO(jwall): This should come from the macrodef instead. + // TODO(jwall): This should come from the FuncDef instead. root: PathBuf, parent_builder: &FileBuilder, mut args: Vec>, ) -> Result, Box> { // 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() { return Err(Box::new(error::BuildError::new( format!( - "Macro called with too many args in file: {}", + "Func called with too many args in file: {}", root.to_string_lossy() ), 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 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::, Rc>::new(); for (i, arg) in args.drain(0..).enumerate() { build_output @@ -101,10 +101,7 @@ pub struct AssertCollector { /// Builder handles building ucg code for a single file. pub struct FileBuilder<'a> { - // FIXME(jwall): This should probably become a working directory instead. working_dir: PathBuf, - // FIXME(jwall): All of the below is build context shared amongst - // various builders. std: Rc>, import_path: &'a Vec, validate_mode: bool, @@ -354,8 +351,8 @@ impl<'a> FileBuilder<'a> { fn check_reserved_word(name: &str) -> bool { match name { - "self" | "assert" | "true" | "false" | "let" | "import" | "as" | "select" | "macro" - | "module" | "env" | "map" | "filter" | "NULL" | "out" | "in" | "is" => true, + "self" | "assert" | "true" | "false" | "let" | "import" | "as" | "select" | "func" + | "module" | "env" | "map" | "filter" | "NULL" | "out" | "in" | "is" | "not" => true, _ => false, } } @@ -1171,26 +1168,26 @@ impl<'a> FileBuilder<'a> { fn eval_call(&self, def: &CallDef, scope: &Scope) -> Result, Box> { let args = &def.arglist; - let v = self.eval_value(&def.macroref, scope)?; - if let &Val::Macro(ref m) = v.deref() { - // Congratulations this is actually a macro. + let v = self.eval_value(&def.funcref, scope)?; + if let &Val::Func(ref def) = v.deref() { + // Congratulations this is actually a function. let mut argvals: Vec> = Vec::new(); for arg in args.iter() { 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( // We should pretty print the selectors here. - format!("{} is not a Macro", v), + format!("{} is not a Function", v), error::ErrorType::TypeFail, def.pos.clone(), ))) } - fn eval_macro_def(&self, def: &mut MacroDef, scope: &Scope) -> Result, Box> { + fn eval_func_def(&self, def: &mut FuncDef, scope: &Scope) -> Result, Box> { 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. @@ -1261,7 +1258,7 @@ impl<'a> FileBuilder<'a> { fn eval_functional_list_processing( &self, elems: &Vec>, - def: &MacroDef, + def: &FuncDef, typ: ProcessingOpType, ) -> Result, Box> { let mut out = Vec::new(); @@ -1290,7 +1287,7 @@ impl<'a> FileBuilder<'a> { fn eval_functional_tuple_processing( &self, fs: &Vec<(PositionedItem, Rc)>, - def: &MacroDef, + def: &FuncDef, typ: ProcessingOpType, ) -> Result, Box> { let mut out = Vec::new(); @@ -1358,12 +1355,12 @@ impl<'a> FileBuilder<'a> { fn eval_reduce_op(&self, def: &ReduceOpDef, scope: &Scope) -> Result, Box> { let maybe_target = self.eval_expr(&def.target, 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 macdef = match maybe_mac.as_ref() { - &Val::Macro(ref macdef) => macdef, + let maybe_mac = self.eval_value(&Value::Symbol(def.func.clone()), &self.scope.clone())?; + let funcdef = match maybe_mac.as_ref() { + &Val::Func(ref funcdef) => funcdef, _ => { return Err(Box::new(error::BuildError::new( - format!("Expected macro but got {:?}", def.mac), + format!("Expected func but got {:?}", def.func), error::ErrorType::TypeFail, def.pos.clone(), ))); @@ -1373,7 +1370,7 @@ impl<'a> FileBuilder<'a> { &Val::List(ref elems) => { for item in elems.iter() { 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; } } @@ -1384,14 +1381,14 @@ impl<'a> FileBuilder<'a> { Rc::new(Val::Str(name.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; } } &Val::Str(ref s) => { for gc in s.graphemes(true) { 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; } } @@ -1412,7 +1409,7 @@ impl<'a> FileBuilder<'a> { fn eval_functional_string_processing( &self, s: &str, - def: &MacroDef, + def: &FuncDef, typ: ProcessingOpType, ) -> Result, Box> { let mut result = String::new(); @@ -1466,12 +1463,12 @@ impl<'a> FileBuilder<'a> { scope: &Scope, ) -> Result, Box> { 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() { - &Val::Macro(ref macdef) => macdef, + &Val::Func(ref macdef) => macdef, _ => { return Err(Box::new(error::BuildError::new( - format!("Expected macro but got {:?}", def.mac), + format!("Expected func but got {:?}", def.func), error::ErrorType::TypeFail, def.pos.clone(), ))); @@ -1578,7 +1575,7 @@ impl<'a> FileBuilder<'a> { | &Val::Int(_) | &Val::Str(_) | &Val::List(_) - | &Val::Macro(_) + | &Val::Func(_) | &Val::Module(_) => { // record an assertion type-failure result. let msg = format!( @@ -1737,7 +1734,7 @@ impl<'a> FileBuilder<'a> { "float" => val.is_float(), "tuple" => val.is_tuple(), "list" => val.is_list(), - "macro" => val.is_macro(), + "func" => val.is_func(), "module" => val.is_module(), other => { 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::Format(ref def) => self.eval_format(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(); - self.eval_macro_def(&mut def_clone, scope) + self.eval_func_def(&mut def_clone, scope) } &Expression::Module(ref def) => { let mut def_clone = def.clone(); diff --git a/src/build/test.rs b/src/build/test.rs index 36f8ba9..0037a9e 100644 --- a/src/build/test.rs +++ b/src/build/test.rs @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. use super::assets::MemoryCache; -use super::{CallDef, FileBuilder, MacroDef, SelectDef, Val}; +use super::{FileBuilder, SelectDef, Val}; use crate::ast::*; 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] #[should_panic(expected = "Expected String but got Integer in Select expression")] fn test_select_expr_not_a_string() { diff --git a/src/convert/env.rs b/src/convert/env.rs index 509967f..2e3198b 100644 --- a/src/convert/env.rs +++ b/src/convert/env.rs @@ -78,9 +78,9 @@ impl EnvConverter { &Val::Tuple(ref flds) => { self.convert_tuple(flds, w)?; } - &Val::Macro(ref _def) => { + &Val::Func(ref _def) => { // This is ignored - eprintln!("Skipping macro..."); + eprintln!("Skipping func..."); } &Val::Env(ref _fs) => { // This is ignored diff --git a/src/convert/flags.rs b/src/convert/flags.rs index c7544b1..8a24e6a 100644 --- a/src/convert/flags.rs +++ b/src/convert/flags.rs @@ -41,7 +41,7 @@ impl FlagConverter { // first of all we need to make sure that each &Val is only a primitive type. for v in def.iter() { 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!( "Skipping non primitive val in list for flag {}{}", pfx, name @@ -96,7 +96,7 @@ impl FlagConverter { } } } - &Val::Macro(ref _def) => { + &Val::Func(ref _def) => { // This is ignored eprintln!("Skipping macro..."); } diff --git a/src/convert/json.rs b/src/convert/json.rs index 602c5e6..265c542 100644 --- a/src/convert/json.rs +++ b/src/convert/json.rs @@ -75,8 +75,8 @@ impl JsonConverter { serde_json::Value::Number(n) } &Val::Str(ref s) => serde_json::Value::String(s.clone()), - &Val::Macro(_) => { - eprintln!("Skipping macro encoding as null..."); + &Val::Func(_) => { + eprintln!("Skipping func encoding as null..."); serde_json::Value::Null } &Val::Module(_) => { diff --git a/src/convert/toml.rs b/src/convert/toml.rs index 4b4bac7..1e6f651 100644 --- a/src/convert/toml.rs +++ b/src/convert/toml.rs @@ -69,8 +69,8 @@ impl TomlConverter { &Val::Float(f) => toml::Value::Float(f), &Val::Int(i) => toml::Value::Integer(i), &Val::Str(ref s) => toml::Value::String(s.clone()), - &Val::Macro(_) => { - let err = SimpleError::new("Macros are not allowed in Toml Conversions!"); + &Val::Func(_) => { + let err = SimpleError::new("Functions are not allowed in Toml Conversions!"); return Err(Box::new(err)); } &Val::Module(_) => { diff --git a/src/convert/yaml.rs b/src/convert/yaml.rs index 94142b7..391d224 100644 --- a/src/convert/yaml.rs +++ b/src/convert/yaml.rs @@ -61,8 +61,8 @@ impl YamlConverter { _ => panic!("Int is too large or not a Number {}", i), }, &Val::Str(ref s) => serde_yaml::Value::String(s.clone()), - &Val::Macro(_) => { - eprintln!("Skipping macro encoding as null..."); + &Val::Func(_) => { + eprintln!("Skipping func encoding as null..."); serde_yaml::Value::Null } &Val::Module(_) => { diff --git a/src/parse/mod.rs b/src/parse/mod.rs index e2bd776..262295c 100644 --- a/src/parse/mod.rs +++ b/src/parse/mod.rs @@ -341,7 +341,7 @@ make_fn!( ) ); -fn tuple_to_macro<'a>( +fn tuple_to_func<'a>( pos: Position, vals: Option>, val: Expression, @@ -357,7 +357,7 @@ fn tuple_to_macro<'a>( val: s.to_string(), }) .collect(); - Ok(Expression::Macro(MacroDef { + Ok(Expression::Func(FuncDef { scope: None, argdefs: arglist, fields: Box::new(val), @@ -401,10 +401,10 @@ fn module_expression(input: SliceIter) -> Result, Expres } } -fn macro_expression(input: SliceIter) -> Result, Expression> { +fn func_expression(input: SliceIter) -> Result, Expression> { let parsed = do_each!(input, pos => pos, - _ => word!("macro"), + _ => word!("func"), _ => must!(punct!("(")), arglist => trace_parse!(optional!(arglist)), _ => must!(punct!(")")), @@ -416,10 +416,10 @@ fn macro_expression(input: SliceIter) -> Result, Express Result::Abort(e) => Result::Abort(e), Result::Fail(e) => Result::Fail(e), 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), Err(e) => Result::Fail(Error::caused_by( - "Invalid Macro syntax", + "Invalid func syntax", Box::new(e), Box::new(rest.clone()), )), @@ -522,7 +522,7 @@ fn tuple_to_call<'a>( ) -> ConvertResult<'a, Expression> { if let Value::Symbol(_) = val { Ok(Expression::Call(CallDef { - macroref: val, + funcref: val, arglist: exprs.unwrap_or_else(|| Vec::new()), pos: (&input).into(), })) @@ -562,12 +562,12 @@ make_fn!( do_each!( pos => pos, _ => word!("reduce"), - macroname => must!(match_type!(BAREWORD)), + funcname => must!(match_type!(BAREWORD)), acc => must!(trace_parse!(non_op_expression)), _ => must!(punct!(",")), tgt => must!(trace_parse!(non_op_expression)), (Expression::FuncOp(FuncOpDef::Reduce(ReduceOpDef{ - mac: (¯oname).into(), + func: (&funcname).into(), acc: Box::new(acc), target: Box::new(tgt), pos: pos, @@ -580,10 +580,10 @@ make_fn!( do_each!( pos => pos, _ => word!("map"), - macroname => must!(match_type!(BAREWORD)), + funcname => must!(match_type!(BAREWORD)), list => must!(trace_parse!(non_op_expression)), (Expression::FuncOp(FuncOpDef::Map(MapFilterOpDef{ - mac: (¯oname).into(), + func: (&funcname).into(), target: Box::new(list), pos: pos, }))) @@ -595,10 +595,10 @@ make_fn!( do_each!( pos => pos, _ => word!("filter"), - macroname => must!(match_type!(BAREWORD)), + funcname => must!(match_type!(BAREWORD)), list => must!(trace_parse!(non_op_expression)), (Expression::FuncOp(FuncOpDef::Filter(MapFilterOpDef{ - mac: (¯oname).into(), + func: (&funcname).into(), target: Box::new(list), pos: pos, }))) @@ -696,7 +696,7 @@ make_fn!( non_op_expression, Expression>, either!( trace_parse!(func_op_expression), - trace_parse!(macro_expression), + trace_parse!(func_expression), trace_parse!(import_expression), trace_parse!(not_expression), trace_parse!(fail_expression), diff --git a/src/tokenizer/mod.rs b/src/tokenizer/mod.rs index 8c6ae22..b0deee7 100644 --- a/src/tokenizer/mod.rs +++ b/src/tokenizer/mod.rs @@ -286,8 +286,8 @@ make_fn!(failtok, do_text_token_tok!(TokenType::BAREWORD, "fail", WS) ); -make_fn!(macrotok, - do_text_token_tok!(TokenType::BAREWORD, "macro", WS) +make_fn!(functok, + do_text_token_tok!(TokenType::BAREWORD, "func", WS) ); make_fn!(moduletok, @@ -427,7 +427,7 @@ fn token<'a>(input: OffsetStrIter<'a>) -> Result, Token> { selecttok, asserttok, failtok, - macrotok, + functok, moduletok, importtok, includetok, diff --git a/src/tokenizer/test.rs b/src/tokenizer/test.rs index c05afc2..a5453c6 100644 --- a/src/tokenizer/test.rs +++ b/src/tokenizer/test.rs @@ -154,7 +154,7 @@ fn test_lteqtok() { #[test] fn test_tokenize_one_of_each() { 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 == < > <= >= !=", ); let result = tokenize(input.clone()); diff --git a/std/functional.ucg b/std/functional.ucg index 426f8f6..32ef535 100644 --- a/std/functional.ucg +++ b/std/functional.ucg @@ -1,7 +1,7 @@ let maybe = module{ val = NULL, } => { - let do = macro(op) => select (mod.val != NULL), NULL, { + let do = func (op) => select (mod.val != NULL), NULL, { true = op(mod.val), }; }; @@ -9,9 +9,9 @@ let maybe = module{ let if = module{ test = false, } => { - let do = macro(op, arg) => select mod.test, arg, { + let do = func (op, arg) => select mod.test, arg, { true = op(arg), }; }; -let identity = macro(arg) => arg; \ No newline at end of file +let identity = func (arg) => arg; \ No newline at end of file diff --git a/std/lists.ucg b/std/lists.ucg index 85fd910..2d9c200 100644 --- a/std/lists.ucg +++ b/std/lists.ucg @@ -2,7 +2,7 @@ let str_join = module{ sep=" ", list=NULL, } => { - let joiner = macro(acc, item) => select (acc.out == ""), NULL, { + let joiner = func (acc, item) => select (acc.out == ""), NULL, { true = acc{ out="@@" % (acc.out,item), }, @@ -17,7 +17,7 @@ let str_join = module{ let len = module{ list = NULL, } => { - let counter = macro(acc, item) => acc + 1; + let counter = func (acc, item) => acc + 1; let result = reduce counter 0, (mod.list); }; @@ -25,7 +25,7 @@ let len = module{ let reverse = module{ list = NULL, } => { - let reducer = macro(acc, item) => [item] + acc; + let reducer = func (acc, item) => [item] + acc; let result = reduce reducer [], (mod.list); }; @@ -35,7 +35,7 @@ let enumerate = module{ step = 1, list = NULL, } => { - let reducer = macro(acc, item) => acc{ + let reducer = func (acc, item) => acc{ count = acc.count + acc.step, list=acc.list + [[acc.count, item]], }; @@ -50,7 +50,7 @@ let zip = module{ list1 = 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 len2 = reduce counter 0, (mod.list2); @@ -60,7 +60,7 @@ let zip = module{ 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)]], idxs = acc.idxs + [item] }; diff --git a/std/schema.ucg b/std/schema.ucg index 477f5a5..6f50600 100644 --- a/std/schema.ucg +++ b/std/schema.ucg @@ -7,21 +7,21 @@ let base_types = [ "null", "tuple", "list", - "macro", + "func", "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}, false = acc, }; // 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. // 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, }; @@ -36,10 +36,10 @@ let any = module { } => { 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), }; - 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; }; @@ -51,7 +51,7 @@ let any = module { // recurse into nested tuples. // // 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. let shaped = module { // The source value to validate @@ -68,9 +68,9 @@ let shaped = module { } => { 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, { true = schema.shaped{val=value, shape=acc.shape.(name)}.result, }, @@ -84,7 +84,7 @@ let shaped = module { null = simple_handler(mod.val, mod.shape), tuple = (reduce tuple_handler {shape=mod.shape, ok=false}, (mod.val)).ok, 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), }; }; \ No newline at end of file diff --git a/std/tests/functional_test.ucg b/std/tests/functional_test.ucg index b6b7486..e08da57 100644 --- a/std/tests/functional_test.ucg +++ b/std/tests/functional_test.ucg @@ -1,7 +1,7 @@ let t = (import "std/testing.ucg").asserts{}; let f = (import "std/functional.ucg"); -let op = macro(arg) => arg{foo="bar"}; +let op = func (arg) => arg{foo="bar"}; assert t.equal{ left = f.maybe{val=NULL}.do(op), diff --git a/std/tests/schema_test.ucg b/std/tests/schema_test.ucg index 35d67ff..2da3498 100644 --- a/std/tests/schema_test.ucg +++ b/std/tests/schema_test.ucg @@ -52,8 +52,8 @@ assert t.equal{ }; assert t.equal{ - left = schema.base_type_of(macro(arg) => arg), - right = "macro", + left = schema.base_type_of(func(arg) => arg), + right = "func", }; assert t.equal{ diff --git a/std/tuples.ucg b/std/tuples.ucg index 7e40fc5..ccb409c 100644 --- a/std/tuples.ucg +++ b/std/tuples.ucg @@ -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), }; @@ -10,7 +10,7 @@ let fields = module{ // First we check that mod.tpl is a tuple. 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); }; @@ -23,7 +23,7 @@ let values = module{ // First we check that mod.tpl is a tuple. 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); }; @@ -35,7 +35,7 @@ let iter = module{ // First we check that mod.tpl is a tuple. 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); }; @@ -47,7 +47,7 @@ let strip_nulls = module{ // First we check that mod.tpl is a tuple. assert_tuple(mod.tpl); - let filterer = macro(name, value) => value != NULL; + let filterer = func (name, value) => value != NULL; let result = filter filterer (mod.tpl); }; @@ -62,7 +62,7 @@ let has_fields = module{ 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); }; @@ -90,7 +90,7 @@ let field_type = module{ 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. false = true, // if this isn't the field then we propagate true });