mirror of
https://github.com/zaphar/ucg.git
synced 2025-07-22 18:19:54 -04:00
parent
0e5751c2b0
commit
d9b2c0cb00
@ -1,3 +1,5 @@
|
|||||||
|
let t = import "std/testing.ucg".asserts{};
|
||||||
|
|
||||||
let test_empty_mod = module {
|
let test_empty_mod = module {
|
||||||
} => {
|
} => {
|
||||||
};
|
};
|
||||||
@ -67,4 +69,44 @@ assert {
|
|||||||
assert {
|
assert {
|
||||||
ok = embedded_mod{dep_value="Some"}.embedded_def{}.value == "None",
|
ok = embedded_mod{dep_value="Some"}.embedded_def{}.value == "None",
|
||||||
desc = "embedded_mod{dep_value=\"Some\"}.embedded_def{}.value == \"None\"",
|
desc = "embedded_mod{dep_value=\"Some\"}.embedded_def{}.value == \"None\"",
|
||||||
|
};
|
||||||
|
|
||||||
|
let export_module = module {
|
||||||
|
foo = "",
|
||||||
|
} => (result) {
|
||||||
|
let foo = mod.foo;
|
||||||
|
|
||||||
|
let result = {
|
||||||
|
out_foo = foo,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
assert t.ok{
|
||||||
|
test = out_foo in export_module{foo="bar"},
|
||||||
|
desc = "out_foo is in our output tuple",
|
||||||
|
};
|
||||||
|
|
||||||
|
assert t.equal{
|
||||||
|
left = export_module{foo="bar"},
|
||||||
|
right = {out_foo = "bar"},
|
||||||
|
};
|
||||||
|
|
||||||
|
let export_module_tuple = module {
|
||||||
|
foo = "",
|
||||||
|
} => ({quux = result.out_foo}) {
|
||||||
|
let foo = mod.foo;
|
||||||
|
|
||||||
|
let result = {
|
||||||
|
out_foo = foo,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
assert t.ok{
|
||||||
|
test = quux in export_module_tuple{foo="bar"},
|
||||||
|
desc = "quux is in our output tuple",
|
||||||
|
};
|
||||||
|
|
||||||
|
assert t.equal{
|
||||||
|
left = export_module_tuple{foo="bar"},
|
||||||
|
right = {quux = "bar"},
|
||||||
};
|
};
|
@ -535,6 +535,7 @@ pub struct ModuleDef {
|
|||||||
pub scope: Option<Scope>,
|
pub scope: Option<Scope>,
|
||||||
pub pos: Position,
|
pub pos: Position,
|
||||||
pub arg_set: FieldList,
|
pub arg_set: FieldList,
|
||||||
|
pub out_expr: Option<Box<Expression>>,
|
||||||
pub arg_tuple: Option<Rc<Val>>,
|
pub arg_tuple: Option<Rc<Val>>,
|
||||||
pub statements: Vec<Statement>,
|
pub statements: Vec<Statement>,
|
||||||
}
|
}
|
||||||
@ -545,11 +546,16 @@ impl ModuleDef {
|
|||||||
scope: None,
|
scope: None,
|
||||||
pos: pos.into(),
|
pos: pos.into(),
|
||||||
arg_set: arg_set,
|
arg_set: arg_set,
|
||||||
|
out_expr: None,
|
||||||
arg_tuple: None,
|
arg_tuple: None,
|
||||||
statements: stmts,
|
statements: stmts,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn set_out_expr(&mut self, expr: Expression) {
|
||||||
|
self.out_expr = Some(Box::new(expr));
|
||||||
|
}
|
||||||
|
|
||||||
pub fn imports_to_absolute(&mut self, base: PathBuf) {
|
pub fn imports_to_absolute(&mut self, base: PathBuf) {
|
||||||
let rewrite_import = |e: &mut Expression| {
|
let rewrite_import = |e: &mut Expression| {
|
||||||
if let Expression::Include(ref mut def) = e {
|
if let Expression::Include(ref mut def) = e {
|
||||||
|
112
src/build/mod.rs
112
src/build/mod.rs
@ -1134,6 +1134,68 @@ impl<'a> FileBuilder<'a> {
|
|||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn eval_module_copy(
|
||||||
|
&self,
|
||||||
|
def: &CopyDef,
|
||||||
|
mod_def: &ModuleDef,
|
||||||
|
scope: &Scope,
|
||||||
|
) -> Result<Rc<Val>, Box<dyn Error>> {
|
||||||
|
let maybe_tpl = mod_def.clone().arg_tuple.unwrap().clone();
|
||||||
|
if let &Val::Tuple(ref src_fields) = maybe_tpl.as_ref() {
|
||||||
|
// 1. First we create a builder.
|
||||||
|
// TODO(jwall): This file should optionally come from the module def itself.
|
||||||
|
let mut b = self.clone_builder();
|
||||||
|
b.is_module = true;
|
||||||
|
// 2. We construct an argument tuple by copying from the defs
|
||||||
|
// argset.
|
||||||
|
// Push our base tuple on the stack so the copy can use
|
||||||
|
// self to reference it.
|
||||||
|
let child_scope = scope.spawn_child().set_curr_val(maybe_tpl.clone());
|
||||||
|
let mod_args = self.copy_from_base(src_fields, &def.fields, &child_scope)?;
|
||||||
|
// put our copied parameters tuple in our builder under the mod key.
|
||||||
|
let mod_key = PositionedItem::new_with_pos(String::from("mod"), Position::new(0, 0, 0));
|
||||||
|
match b.scope.build_output.entry(mod_key) {
|
||||||
|
Entry::Occupied(e) => {
|
||||||
|
return Err(error::BuildError::with_pos(
|
||||||
|
format!(
|
||||||
|
"Binding \
|
||||||
|
for {:?} already \
|
||||||
|
exists in module",
|
||||||
|
e.key(),
|
||||||
|
),
|
||||||
|
error::ErrorType::DuplicateBinding,
|
||||||
|
mod_def.pos.clone(),
|
||||||
|
)
|
||||||
|
.to_boxed());
|
||||||
|
}
|
||||||
|
Entry::Vacant(e) => {
|
||||||
|
e.insert(mod_args.clone());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 4. Evaluate all the statements using the builder.
|
||||||
|
b.eval_stmts(&mod_def.statements)?;
|
||||||
|
if let Some(ref expr) = mod_def.out_expr {
|
||||||
|
// 5. Produce the out expression in the context of the statements
|
||||||
|
// we evaluated previously.
|
||||||
|
return b.eval_expr(expr, &b.scope);
|
||||||
|
} else {
|
||||||
|
// 5. Take all of the bindings in the module and construct a new
|
||||||
|
// tuple using them.
|
||||||
|
return Ok(b.get_outputs_as_val());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return Err(error::BuildError::with_pos(
|
||||||
|
format!(
|
||||||
|
"Weird value stored in our module parameters slot {:?}",
|
||||||
|
mod_def.arg_tuple
|
||||||
|
),
|
||||||
|
error::ErrorType::TypeFail,
|
||||||
|
def.selector.pos().clone(),
|
||||||
|
)
|
||||||
|
.to_boxed());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn eval_copy(&self, def: &CopyDef, scope: &Scope) -> Result<Rc<Val>, Box<dyn Error>> {
|
fn eval_copy(&self, def: &CopyDef, scope: &Scope) -> Result<Rc<Val>, Box<dyn Error>> {
|
||||||
let v = self.eval_value(&def.selector, scope)?;
|
let v = self.eval_value(&def.selector, scope)?;
|
||||||
if let &Val::Tuple(ref src_fields) = v.as_ref() {
|
if let &Val::Tuple(ref src_fields) = v.as_ref() {
|
||||||
@ -1141,55 +1203,7 @@ impl<'a> FileBuilder<'a> {
|
|||||||
return self.copy_from_base(&src_fields, &def.fields, &child_scope);
|
return self.copy_from_base(&src_fields, &def.fields, &child_scope);
|
||||||
}
|
}
|
||||||
if let &Val::Module(ref mod_def) = v.as_ref() {
|
if let &Val::Module(ref mod_def) = v.as_ref() {
|
||||||
let maybe_tpl = mod_def.clone().arg_tuple.unwrap().clone();
|
return self.eval_module_copy(def, mod_def, scope);
|
||||||
if let &Val::Tuple(ref src_fields) = maybe_tpl.as_ref() {
|
|
||||||
// 1. First we create a builder.
|
|
||||||
// TODO(jwall): This file should optionally come from the module def itself.
|
|
||||||
let mut b = self.clone_builder();
|
|
||||||
b.is_module = true;
|
|
||||||
// 2. We construct an argument tuple by copying from the defs
|
|
||||||
// argset.
|
|
||||||
// Push our base tuple on the stack so the copy can use
|
|
||||||
// self to reference it.
|
|
||||||
let child_scope = scope.spawn_child().set_curr_val(maybe_tpl.clone());
|
|
||||||
let mod_args = self.copy_from_base(src_fields, &def.fields, &child_scope)?;
|
|
||||||
// put our copied parameters tuple in our builder under the mod key.
|
|
||||||
let mod_key =
|
|
||||||
PositionedItem::new_with_pos(String::from("mod"), Position::new(0, 0, 0));
|
|
||||||
match b.scope.build_output.entry(mod_key) {
|
|
||||||
Entry::Occupied(e) => {
|
|
||||||
return Err(error::BuildError::with_pos(
|
|
||||||
format!(
|
|
||||||
"Binding \
|
|
||||||
for {:?} already \
|
|
||||||
exists in module",
|
|
||||||
e.key(),
|
|
||||||
),
|
|
||||||
error::ErrorType::DuplicateBinding,
|
|
||||||
mod_def.pos.clone(),
|
|
||||||
)
|
|
||||||
.to_boxed());
|
|
||||||
}
|
|
||||||
Entry::Vacant(e) => {
|
|
||||||
e.insert(mod_args.clone());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// 4. Evaluate all the statements using the builder.
|
|
||||||
b.eval_stmts(&mod_def.statements)?;
|
|
||||||
// 5. Take all of the bindings in the module and construct a new
|
|
||||||
// tuple using them.
|
|
||||||
return Ok(b.get_outputs_as_val());
|
|
||||||
} else {
|
|
||||||
return Err(error::BuildError::with_pos(
|
|
||||||
format!(
|
|
||||||
"Weird value stored in our module parameters slot {:?}",
|
|
||||||
mod_def.arg_tuple
|
|
||||||
),
|
|
||||||
error::ErrorType::TypeFail,
|
|
||||||
def.selector.pos().clone(),
|
|
||||||
)
|
|
||||||
.to_boxed());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Err(error::BuildError::with_pos(
|
Err(error::BuildError::with_pos(
|
||||||
format!("Expected Tuple or Module but got ({})", v),
|
format!("Expected Tuple or Module but got ({})", v),
|
||||||
|
@ -379,17 +379,28 @@ fn module_expression(input: SliceIter<Token>) -> Result<SliceIter<Token>, Expres
|
|||||||
_ => optional!(punct!(",")),
|
_ => optional!(punct!(",")),
|
||||||
_ => must!(punct!("}")),
|
_ => must!(punct!("}")),
|
||||||
_ => must!(punct!("=>")),
|
_ => must!(punct!("=>")),
|
||||||
|
out_expr => optional!(
|
||||||
|
do_each!(
|
||||||
|
_ => punct!("("),
|
||||||
|
expr => must!(expression),
|
||||||
|
_ => must!(punct!(")")),
|
||||||
|
(expr)
|
||||||
|
)
|
||||||
|
),
|
||||||
_ => must!(punct!("{")),
|
_ => must!(punct!("{")),
|
||||||
stmt_list => trace_parse!(repeat!(statement)),
|
stmt_list => trace_parse!(repeat!(statement)),
|
||||||
_ => must!(punct!("}")),
|
_ => must!(punct!("}")),
|
||||||
(pos, arglist, stmt_list)
|
(pos, arglist, out_expr, stmt_list)
|
||||||
);
|
);
|
||||||
match parsed {
|
match parsed {
|
||||||
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, stmt_list)) => {
|
Result::Complete(rest, (pos, arglist, out_expr, stmt_list)) => {
|
||||||
let def = ModuleDef::new(arglist.unwrap_or_else(|| Vec::new()), stmt_list, pos);
|
let mut def = ModuleDef::new(arglist.unwrap_or_else(|| Vec::new()), stmt_list, pos);
|
||||||
|
if let Some(expr) = out_expr {
|
||||||
|
def.set_out_expr(expr);
|
||||||
|
}
|
||||||
//eprintln!(
|
//eprintln!(
|
||||||
// "module def at: {:?} arg_typle len {} stmts len {}",
|
// "module def at: {:?} arg_typle len {} stmts len {}",
|
||||||
// def.pos,
|
// def.pos,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user