mirror of
https://github.com/zaphar/ucg.git
synced 2025-07-22 18:19:54 -04:00
FEATURE: Add a function to the mod binding that imports the containing package.
This commit is contained in:
parent
4afac26497
commit
0e41a40ab3
@ -576,9 +576,9 @@ let embedded_with_params = top_mod{deep_value = "Some"};
|
|||||||
embedded_with_params.embedded.value == "Some";
|
embedded_with_params.embedded.value == "Some";
|
||||||
```
|
```
|
||||||
|
|
||||||
### Out Expressions
|
### Return Expressions
|
||||||
|
|
||||||
If there is an out expression then the module will only export the result of
|
If there is a return expression then the module will only export the result of
|
||||||
that expression. The out expression is computed after the last statement in the
|
that expression. The out expression is computed after the last statement in the
|
||||||
module has been evaluated.
|
module has been evaluated.
|
||||||
|
|
||||||
@ -611,6 +611,29 @@ is that modules can be called recursively. They are the only expression that is
|
|||||||
capable of recursion in UCG. Recursion can be done by importing the module's file
|
capable of recursion in UCG. Recursion can be done by importing the module's file
|
||||||
inside the module's definition and using it as normal.
|
inside the module's definition and using it as normal.
|
||||||
|
|
||||||
|
There is a convenience function `mod.pkg` in the mod binding for a module. That imports the
|
||||||
|
package/file that the module was declared in. This binding is only present if the module
|
||||||
|
was declared in a file. Modules created as part of an eval will not have it.
|
||||||
|
|
||||||
|
```
|
||||||
|
let recursive = module {
|
||||||
|
counter=1,
|
||||||
|
stop=10,
|
||||||
|
} => (result) {
|
||||||
|
// import our enclosing file again. Careful since calling this function
|
||||||
|
// means that if you instantiate this module in the same file it is
|
||||||
|
// declared in you will trigger an import cycle error.
|
||||||
|
let pkg = mod.pkg();
|
||||||
|
|
||||||
|
let result = select mod.counter != mod.stop, {
|
||||||
|
true = [mod.start] + pkg.recursive{counter=mod.counter+1},
|
||||||
|
false = [mod.start],
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
recursive{} == [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
|
||||||
|
```
|
||||||
|
|
||||||
Fail Expression
|
Fail Expression
|
||||||
---------------
|
---------------
|
||||||
|
|
||||||
|
@ -1071,7 +1071,7 @@ impl<'a> FileBuilder<'a> {
|
|||||||
Rc::new(Val::Tuple(fields))
|
Rc::new(Val::Tuple(fields))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn copy_from_base(
|
fn copy_fields_from_base(
|
||||||
&self,
|
&self,
|
||||||
src_fields: &Vec<(String, Rc<Val>)>,
|
src_fields: &Vec<(String, Rc<Val>)>,
|
||||||
overrides: &Vec<(Token, Expression)>,
|
overrides: &Vec<(Token, Expression)>,
|
||||||
@ -1166,9 +1166,29 @@ impl<'a> FileBuilder<'a> {
|
|||||||
// Push our base tuple on the stack so the copy can use
|
// Push our base tuple on the stack so the copy can use
|
||||||
// self to reference it.
|
// self to reference it.
|
||||||
let child_scope = scope.spawn_child().set_curr_val(maybe_tpl.clone());
|
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)?;
|
let mut overrides = Vec::new();
|
||||||
|
if let Some(ref path) = mod_def.pos.file {
|
||||||
|
overrides.push((
|
||||||
|
Token::new("pkg", TokenType::BAREWORD, def.pos.clone()),
|
||||||
|
Expression::Func(FuncDef {
|
||||||
|
scope: None,
|
||||||
|
argdefs: Vec::new(),
|
||||||
|
fields: Box::new(Expression::Import(ImportDef {
|
||||||
|
pos: def.pos.clone(),
|
||||||
|
path: Token::new(
|
||||||
|
path.to_string_lossy().to_string(),
|
||||||
|
TokenType::QUOTED,
|
||||||
|
def.pos.clone(),
|
||||||
|
),
|
||||||
|
})),
|
||||||
|
pos: def.pos.clone(),
|
||||||
|
}),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
overrides.extend(def.fields.iter().cloned());
|
||||||
|
let mod_args = self.copy_fields_from_base(src_fields, &overrides, &child_scope)?;
|
||||||
// put our copied parameters tuple in our builder under the mod key.
|
// 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));
|
let mod_key = PositionedItem::new_with_pos(String::from("mod"), def.pos.clone());
|
||||||
match b.scope.build_output.entry(mod_key) {
|
match b.scope.build_output.entry(mod_key) {
|
||||||
Entry::Occupied(e) => {
|
Entry::Occupied(e) => {
|
||||||
return Err(error::BuildError::with_pos(
|
return Err(error::BuildError::with_pos(
|
||||||
@ -1215,7 +1235,7 @@ impl<'a> FileBuilder<'a> {
|
|||||||
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() {
|
||||||
let child_scope = scope.spawn_child().set_curr_val(v.clone());
|
let child_scope = scope.spawn_child().set_curr_val(v.clone());
|
||||||
return self.copy_from_base(&src_fields, &def.fields, &child_scope);
|
return self.copy_fields_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() {
|
||||||
return self.eval_module_copy(def, mod_def, scope);
|
return self.eval_module_copy(def, mod_def, scope);
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
let maybe = module{
|
let maybe = module{
|
||||||
val = NULL,
|
val = NULL,
|
||||||
} => ({do=do, is_null=is_null, or=or, unwrap=unwrap, expect=expect}) {
|
} => ({do=do, is_null=is_null, or=or, unwrap=unwrap, expect=expect}) {
|
||||||
let maybe = import "std/functional.ucg".maybe;
|
let maybe = mod.pkg().maybe;
|
||||||
|
|
||||||
let do = func (op) => select (mod.val != NULL), maybe{val=NULL}, {
|
let do = func (op) => select (mod.val != NULL), maybe{val=NULL}, {
|
||||||
true = maybe{val=op(mod.val)},
|
true = maybe{val=op(mod.val)},
|
||||||
|
@ -77,7 +77,7 @@ let slice = module {
|
|||||||
end = NULL,
|
end = NULL,
|
||||||
list = NULL,
|
list = NULL,
|
||||||
} => (result) {
|
} => (result) {
|
||||||
let list = import "std/lists.ucg";
|
let list = mod.pkg();
|
||||||
|
|
||||||
let list_len = list.len(mod.list);
|
let list_len = list.len(mod.list);
|
||||||
|
|
||||||
@ -111,7 +111,7 @@ let zip = module{
|
|||||||
list1 = NULL,
|
list1 = NULL,
|
||||||
list2 = NULL,
|
list2 = NULL,
|
||||||
} => (result) {
|
} => (result) {
|
||||||
let len = import "std/lists.ucg".len;
|
let len = mod.pkg().len;
|
||||||
|
|
||||||
// Compute the length of each list.
|
// Compute the length of each list.
|
||||||
let len1 = len(mod.list1);
|
let len1 = len(mod.list1);
|
||||||
@ -169,7 +169,7 @@ let ops = module{
|
|||||||
reverse=reverse,
|
reverse=reverse,
|
||||||
list=list,
|
list=list,
|
||||||
}) {
|
}) {
|
||||||
let super = import "std/lists.ucg";
|
let super = mod.pkg();
|
||||||
let list = mod.list;
|
let list = mod.list;
|
||||||
let len = super.len(mod.list);
|
let len = super.len(mod.list);
|
||||||
let str_join = func(sep) => super.str_join{list=mod.list, sep=sep};
|
let str_join = func(sep) => super.str_join{list=mod.list, sep=sep};
|
||||||
|
@ -32,7 +32,7 @@ let any = module {
|
|||||||
// The set of allowed type shapes it can be.
|
// The set of allowed type shapes it can be.
|
||||||
types=[],
|
types=[],
|
||||||
} => (result) {
|
} => (result) {
|
||||||
let schema = import "std/schema.ucg";
|
let schema = mod.pkg();
|
||||||
|
|
||||||
let reducer = func (acc, t) => acc{
|
let reducer = func (acc, t) => acc{
|
||||||
ok = acc.ok || (schema.shaped{val=acc.val, shape=t}),
|
ok = acc.ok || (schema.shaped{val=acc.val, shape=t}),
|
||||||
@ -66,7 +66,7 @@ let shaped = module {
|
|||||||
// shape it is compared with.
|
// shape it is compared with.
|
||||||
partial = true,
|
partial = true,
|
||||||
} => (result) {
|
} => (result) {
|
||||||
let schema = import "std/schema.ucg";
|
let schema = mod.pkg();
|
||||||
|
|
||||||
let simple_handler = func (val, shape) => val is schema.base_type_of(shape);
|
let simple_handler = func (val, shape) => val is schema.base_type_of(shape);
|
||||||
|
|
||||||
|
@ -65,7 +65,7 @@ let ops = module {
|
|||||||
start = 0,
|
start = 0,
|
||||||
end = len,
|
end = len,
|
||||||
} => (result) {
|
} => (result) {
|
||||||
let filepkg = import "std/strings.ucg";
|
let filepkg = mod.pkg();
|
||||||
let reducer = func(acc, char) => acc{
|
let reducer = func(acc, char) => acc{
|
||||||
counter = acc.counter + 1,
|
counter = acc.counter + 1,
|
||||||
str = select ((acc.counter >= mod.start) && (acc.counter <= mod.end)), acc.str, {
|
str = select ((acc.counter >= mod.start) && (acc.counter <= mod.end)), acc.str, {
|
||||||
|
@ -48,7 +48,7 @@ let ops = module{
|
|||||||
} => ({fields=fields, values=values, iter=iter}) {
|
} => ({fields=fields, values=values, iter=iter}) {
|
||||||
(mod.tpl != NULL) || fail "tpl must not be null";
|
(mod.tpl != NULL) || fail "tpl must not be null";
|
||||||
|
|
||||||
let super = import "std/tuples.ucg";
|
let super = mod.pkg();
|
||||||
|
|
||||||
let fields = func() => super.fields{tpl=mod.tpl};
|
let fields = func() => super.fields{tpl=mod.tpl};
|
||||||
let values = func() => super.values{tpl=mod.tpl};
|
let values = func() => super.values{tpl=mod.tpl};
|
||||||
@ -71,7 +71,7 @@ let has_fields = module{
|
|||||||
tpl = NULL,
|
tpl = NULL,
|
||||||
fields = [],
|
fields = [],
|
||||||
} => (result) {
|
} => (result) {
|
||||||
let lib = import "std/tuples.ucg";
|
let lib = mod.pkg();
|
||||||
// First we check that mod.tpl is a tuple.
|
// First we check that mod.tpl is a tuple.
|
||||||
lib.assert_tuple(mod.tpl);
|
lib.assert_tuple(mod.tpl);
|
||||||
|
|
||||||
@ -86,7 +86,7 @@ let field_type = module{
|
|||||||
field = NULL,
|
field = NULL,
|
||||||
type = NULL,
|
type = NULL,
|
||||||
} => (result) {
|
} => (result) {
|
||||||
let lib = import "std/tuples.ucg";
|
let lib = mod.pkg();
|
||||||
// First we check that mod.tpl is a tuple.
|
// First we check that mod.tpl is a tuple.
|
||||||
lib.assert_tuple(mod.tpl);
|
lib.assert_tuple(mod.tpl);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user