mirror of
https://github.com/zaphar/ucg.git
synced 2025-07-21 18:10:42 -04:00
REFACTOR: Cleanup the syntax for the select expr
This makes it both easier to correctly write a select expression as well as easier to parse and report syntax errors.
This commit is contained in:
parent
f199e0f871
commit
a90df8a362
@ -403,7 +403,7 @@ let test_tpl = {
|
||||
foo = "bar",
|
||||
quux = "baz",
|
||||
};
|
||||
let tpl_mapper = func (name, val) => select name, [name, val], {
|
||||
let tpl_mapper = func (name, val) => select (name, [name, val]) => {
|
||||
"foo" = ["foo", "barbar"],
|
||||
quux = ["cute", "pygmy"],
|
||||
};
|
||||
@ -429,7 +429,7 @@ the item or field staying in the resulting list or tuple.
|
||||
|
||||
```
|
||||
let list2 = ["foo", "bar", "foo", "bar"];
|
||||
let filtrator = func (item) => select item, NULL, {
|
||||
let filtrator = func (item) => select (item, NULL) {
|
||||
foo = item,
|
||||
};
|
||||
|
||||
@ -514,27 +514,27 @@ Conditionals
|
||||
UCG supports a limited conditional expression called a select. A select
|
||||
expression starts with the `select` keyword and is followed by a an expression
|
||||
resolving to a string or boolean naming the field to select, an optional
|
||||
expression resolving to the default value, and finally a tuple literal to
|
||||
select the field from. If the field selected is not in the tuple then the
|
||||
default value will be used. If no default is specified then select will
|
||||
throw a compile failure for the unhandled case.
|
||||
expression resolving to the default value in parenthesis a `=>` and finally a
|
||||
tuple literal to select the field from. If the field selected is not in the
|
||||
tuple then the default value will be used. If no default is specified then
|
||||
select will throw a compile failure for the unhandled case.
|
||||
|
||||
```
|
||||
let want = "baz";
|
||||
|
||||
// field default
|
||||
select want, "quux", {
|
||||
select (want, "quux") => {
|
||||
baz = "foo",
|
||||
fuzz = "bang",
|
||||
}; // result will be "foo"
|
||||
|
||||
// field default
|
||||
select "quack", "quux", {
|
||||
select ("quack", "quux") => {
|
||||
baz = "foo",
|
||||
fuzz = "bang",
|
||||
}; // result will be "quux"
|
||||
|
||||
let ifresult = select true, {
|
||||
let ifresult = select (true) => {
|
||||
true = "true result",
|
||||
false = "false result",
|
||||
}; // result will be "true result"
|
||||
|
@ -49,6 +49,7 @@ import_keyword: "import" ;
|
||||
include_keyword: "include" ;
|
||||
as_keyword: "as" ;
|
||||
func_keyword: "func" ;
|
||||
select_keyword: "select" ;
|
||||
map_keyword: "map" ;
|
||||
reduce_keyword: "map" ;
|
||||
filter_keyword: "filter" ;
|
||||
@ -111,6 +112,12 @@ literal: str | integer | float | list | tuple | null_keyword;
|
||||
grouped: lparen, expr, rparen ;
|
||||
```
|
||||
|
||||
#### Select expressions
|
||||
|
||||
```
|
||||
select_expr: select_keyword, lparen, expr, [comma, expr], fatcomma, tuple ;
|
||||
```
|
||||
|
||||
#### Function Definition
|
||||
|
||||
```
|
||||
@ -189,6 +196,7 @@ trace_expr: trace_keyword, expr ;
|
||||
```
|
||||
non_operator_expr: literal
|
||||
| grouped
|
||||
| select_def
|
||||
| import_expr
|
||||
| funcdef
|
||||
| module_def
|
||||
|
@ -121,8 +121,8 @@ assert {
|
||||
};
|
||||
let want = "foo";
|
||||
assert {
|
||||
ok = select want, 1, { foo=2, } == 2,
|
||||
desc = "select want, 1, { foo=2, } == 2",
|
||||
ok = select (want, 1) => { foo=2, } == 2,
|
||||
desc = "select (want, 1) => { foo=2, } == 2",
|
||||
};
|
||||
|
||||
// Contains comparison operators.
|
||||
|
@ -4,7 +4,7 @@ let list1 = [1, 2, 3, 4];
|
||||
let list2 = ["foo", "bar", "foo", "bar"];
|
||||
|
||||
let mapper = func (item) => item + 1;
|
||||
let filtrator = func (item) => select item, NULL, {
|
||||
let filtrator = func (item) => select (item, NULL) => {
|
||||
foo = item,
|
||||
};
|
||||
|
||||
@ -84,7 +84,7 @@ assert {
|
||||
desc = "map(identity_tpl_mapper, test_tpl) == test_tpl",
|
||||
};
|
||||
|
||||
let tpl_mapper = func (name, val) => select name, [name, val], {
|
||||
let tpl_mapper = func (name, val) => select (name, [name, val]) => {
|
||||
"foo" = ["foo", "barbar"],
|
||||
quux = ["cute", "pygmy"],
|
||||
};
|
||||
|
@ -33,7 +33,7 @@ let embedded_mod = module {
|
||||
deep_value = "None",
|
||||
environ = "None",
|
||||
} => {
|
||||
let env_name = select mod.environ, "qa", {
|
||||
let env_name = select (mod.environ, "qa") => {
|
||||
None = "qa",
|
||||
prod = "prod",
|
||||
qa = "qa",
|
||||
@ -113,7 +113,7 @@ assert t.equal{
|
||||
|
||||
let recursive_module = module {start=1, end=10} => (result) {
|
||||
let this = mod.this;
|
||||
let result = select mod.start != mod.end, mod.start, {
|
||||
let result = select (mod.start != mod.end, mod.start) => {
|
||||
true = this{start=mod.start + 1, end=mod.end},
|
||||
};
|
||||
};
|
||||
|
@ -1,12 +1,12 @@
|
||||
let goodwant = "door1";
|
||||
let badwant = "door4";
|
||||
|
||||
let got = select goodwant, "OOPS", {
|
||||
let got = select (goodwant, "OOPS") => {
|
||||
door1 = "grand prize",
|
||||
door2 = "you lose",
|
||||
};
|
||||
|
||||
let defaultgot = select badwant, "OOPS", {
|
||||
let defaultgot = select (badwant, "OOPS") => {
|
||||
door1 = "grand prize",
|
||||
door2 = "you lose",
|
||||
};
|
||||
@ -23,7 +23,7 @@ assert {
|
||||
// select inside a function
|
||||
|
||||
let condfunc = func (arg) => {
|
||||
output = select arg, NULL, {
|
||||
output = select (arg, NULL) => {
|
||||
opt1 = "yay",
|
||||
opt2 = "boo",
|
||||
},
|
||||
@ -44,7 +44,7 @@ assert {
|
||||
desc = "condfunc(\"invalid\") == {output = NULL}",
|
||||
};
|
||||
|
||||
let iflike = select true, "default", {
|
||||
let iflike = select (true, "default") => {
|
||||
true = "I was true",
|
||||
false = "I was false",
|
||||
};
|
||||
@ -54,7 +54,7 @@ assert {
|
||||
desc = "iflike == \"I was true\"",
|
||||
};
|
||||
|
||||
let no_default_test = func(b) => select b, {
|
||||
let no_default_test = func(b) => select (b) => {
|
||||
true = "I was true",
|
||||
false = "I was false",
|
||||
};
|
||||
@ -73,7 +73,7 @@ let tpl_fields = {
|
||||
test = "foo",
|
||||
};
|
||||
|
||||
let no_default_select_result = select tpl_fields.test == "foo", {
|
||||
let no_default_select_result = select (tpl_fields.test == "foo") => {
|
||||
true = true,
|
||||
false = false,
|
||||
};
|
||||
@ -83,9 +83,9 @@ assert {
|
||||
desc = "no default successfully select true",
|
||||
};
|
||||
|
||||
let nested_select_result_no_defaults = select true, {
|
||||
let nested_select_result_no_defaults = select (true) => {
|
||||
true = true,
|
||||
false = select false, {
|
||||
false = select (false) => {
|
||||
true = fail "whoops! this should never have triggered.",
|
||||
false = true,
|
||||
},
|
||||
|
@ -516,12 +516,13 @@ where
|
||||
}
|
||||
}
|
||||
write!(self.w, "select ")?;
|
||||
write!(self.w, "(")?;
|
||||
self.render_expr(&_def.val)?;
|
||||
write!(self.w, ", ")?;
|
||||
if let Some(ref e) = _def.default {
|
||||
self.render_expr(e)?;
|
||||
write!(self.w, ", ")?;
|
||||
self.render_expr(e)?;
|
||||
}
|
||||
write!(self.w, ") => ")?;
|
||||
self.render_tuple_def(&_def.tuple)?;
|
||||
}
|
||||
Expression::Simple(ref _def) => {
|
||||
|
@ -149,13 +149,13 @@ fn test_out_expr_printing() {
|
||||
|
||||
#[test]
|
||||
fn test_select_expr_no_default_printing() {
|
||||
let input = "select true, {\n true = 1,\n false = 2,\n};";
|
||||
let input = "select (true) => {\n true = 1,\n false = 2,\n};";
|
||||
assert_eq!(print_to_buffer(input), format!("{}\n", input));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_select_expr_with_default_printing() {
|
||||
let input = "select true, 3, {\n true = 1,\n false = 2,\n};";
|
||||
let input = "select (true, 3) => {\n true = 1,\n false = 2,\n};";
|
||||
assert_eq!(print_to_buffer(input), format!("{}\n", input));
|
||||
}
|
||||
|
||||
|
@ -550,10 +550,10 @@ fn test_func_call_wrong_argument_type_compile_failure() {
|
||||
#[test]
|
||||
fn test_select_missed_case_string_no_default_compile_failure() {
|
||||
assert_build_failure(
|
||||
"select \"a\", { b = 1, };",
|
||||
"select (\"a\") => { b = 1, };",
|
||||
vec![
|
||||
Regex::new(r"Unhandled select case with no default").unwrap(),
|
||||
Regex::new(r"line: 1 column: 8").unwrap(),
|
||||
Regex::new(r"line: 1 column: 9").unwrap(),
|
||||
],
|
||||
)
|
||||
}
|
||||
@ -561,10 +561,10 @@ fn test_select_missed_case_string_no_default_compile_failure() {
|
||||
#[test]
|
||||
fn test_select_missed_case_boolean_no_default_compile_failure() {
|
||||
assert_build_failure(
|
||||
"select true, { false = 1, };",
|
||||
"select (true) => { false = 1, };",
|
||||
vec![
|
||||
Regex::new(r"Unhandled select case with no default").unwrap(),
|
||||
Regex::new(r"line: 1 column: 8").unwrap(),
|
||||
Regex::new(r"line: 1 column: 9").unwrap(),
|
||||
],
|
||||
)
|
||||
}
|
||||
@ -578,4 +578,4 @@ fn test_bad_import_path_compile_failure() {
|
||||
Regex::new(r"line: 1 column: 18").unwrap(),
|
||||
],
|
||||
)
|
||||
}
|
||||
}
|
111
src/parse/mod.rs
111
src/parse/mod.rs
@ -461,47 +461,82 @@ fn tuple_to_select<'a>(
|
||||
}
|
||||
}
|
||||
|
||||
fn select_expression(input: SliceIter<Token>) -> Result<SliceIter<Token>, Expression> {
|
||||
let parsed = do_each!(input,
|
||||
make_fn!(
|
||||
alt_select_expression<SliceIter<Token>, Expression>,
|
||||
do_each!(
|
||||
pos => pos,
|
||||
_ => word!("select"),
|
||||
val => do_each!(
|
||||
expr => trace_parse!(must!(expression)),
|
||||
_ => must!(punct!(",")),
|
||||
(expr)
|
||||
),
|
||||
default_and_map => either!(
|
||||
_ => must!(punct!("(")),
|
||||
val => must!(expression),
|
||||
default => optional!(
|
||||
do_each!(
|
||||
default => do_each!(
|
||||
expr => trace_parse!(expression),
|
||||
_ => punct!(","),
|
||||
(expr)
|
||||
),
|
||||
map => trace_parse!(tuple),
|
||||
(Some(default), map)
|
||||
),
|
||||
do_each!(
|
||||
map => trace_parse!(must!(tuple)),
|
||||
(None, map)
|
||||
_ => punct!(","),
|
||||
def => must!(expression),
|
||||
(def)
|
||||
)
|
||||
),
|
||||
(val, default_and_map.0, default_and_map.1)
|
||||
);
|
||||
match parsed {
|
||||
Result::Abort(e) => Result::Abort(e),
|
||||
Result::Fail(e) => Result::Fail(e),
|
||||
Result::Incomplete(offset) => Result::Incomplete(offset),
|
||||
Result::Complete(rest, (val, default, map)) => {
|
||||
match tuple_to_select(input.clone(), val, default, map) {
|
||||
Ok(expr) => Result::Complete(rest, expr),
|
||||
Err(e) => Result::Fail(Error::caused_by(
|
||||
"Invalid Select Expression",
|
||||
Box::new(e),
|
||||
Box::new(rest.clone()),
|
||||
)),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => optional!(punct!(",")),
|
||||
_ => must!(punct!(")")),
|
||||
_ => must!(punct!("=>")),
|
||||
_ => must!(punct!("{")),
|
||||
tpl => must!(field_list),
|
||||
_ => optional!(punct!(",")),
|
||||
_ => must!(punct!("}")),
|
||||
(Expression::Select(SelectDef {
|
||||
val: Box::new(val),
|
||||
default: default.map(|e| Box::new(e)),
|
||||
tuple: tpl,
|
||||
pos: pos,
|
||||
}))
|
||||
)
|
||||
);
|
||||
|
||||
//fn select_expression(input: SliceIter<Token>) -> Result<SliceIter<Token>, Expression> {
|
||||
//let parsed = do_each!(input,
|
||||
//_ => word!("select"),
|
||||
//val => do_each!(
|
||||
//expr => wrap_err!(
|
||||
//trace_parse!(must!(expression)),
|
||||
//"Did you forget a comma after your selector value?"),
|
||||
//_ => must!(punct!(",")),
|
||||
//(expr)
|
||||
//),
|
||||
//default_and_map => either!(
|
||||
//do_each!(
|
||||
//default => do_each!(
|
||||
//expr => trace_parse!(expression),
|
||||
//_ => punct!(","),
|
||||
//(expr)
|
||||
//),
|
||||
//map => trace_parse!(must!(tuple)),
|
||||
//(Some(default), map)
|
||||
//),
|
||||
//do_each!(
|
||||
//map => wrap_err!(
|
||||
//trace_parse!(must!(tuple)),
|
||||
//"Did you forget a comma after your default value?"
|
||||
//),
|
||||
//(None, map)
|
||||
//)
|
||||
//),
|
||||
//(val, default_and_map.0, default_and_map.1)
|
||||
//);
|
||||
//match parsed {
|
||||
//Result::Abort(e) => Result::Abort(e),
|
||||
//Result::Fail(e) => Result::Fail(e),
|
||||
//Result::Incomplete(offset) => Result::Incomplete(offset),
|
||||
//Result::Complete(rest, (val, default, map)) => {
|
||||
//match tuple_to_select(input.clone(), val, default, map) {
|
||||
//Ok(expr) => Result::Complete(rest, expr),
|
||||
//Err(e) => Result::Fail(Error::caused_by(
|
||||
//"Invalid Select Expression",
|
||||
//Box::new(e),
|
||||
//Box::new(rest.clone()),
|
||||
//)),
|
||||
//}
|
||||
//}
|
||||
//}
|
||||
//}
|
||||
|
||||
make_fn!(
|
||||
simple_format_args<SliceIter<Token>, FormatArgs>,
|
||||
@ -764,7 +799,7 @@ make_fn!(
|
||||
trace_parse!(not_expression),
|
||||
trace_parse!(fail_expression),
|
||||
trace_parse!(module_expression),
|
||||
trace_parse!(select_expression),
|
||||
trace_parse!(alt_select_expression),
|
||||
trace_parse!(grouped_expression),
|
||||
trace_parse!(include_expression),
|
||||
trace_parse!(unprefixed_expression)
|
||||
|
@ -18,11 +18,11 @@ let maybe = module{
|
||||
} => ({do=do, is_null=is_null, or=or, unwrap=unwrap, expect=expect}) {
|
||||
let this = mod.this;
|
||||
|
||||
let do = func (op) => select (mod.val != NULL), this{val=NULL}, {
|
||||
let do = func (op) => select ((mod.val != NULL), this{val=NULL}) => {
|
||||
true = this{val=op(mod.val)},
|
||||
};
|
||||
|
||||
let or = func (op) => select (mod.val == NULL), this{val=mod.val}, {
|
||||
let or = func (op) => select ((mod.val == NULL), this{val=mod.val}) => {
|
||||
true = this{val=op()},
|
||||
};
|
||||
|
||||
@ -30,7 +30,7 @@ let maybe = module{
|
||||
|
||||
let unwrap = func() => mod.val;
|
||||
|
||||
let expect = func(msg) => select mod.val != NULL, fail msg, {
|
||||
let expect = func(msg) => select (mod.val != NULL, fail msg) => {
|
||||
true = mod.val,
|
||||
};
|
||||
};
|
||||
|
@ -9,7 +9,7 @@ let str_join = module{
|
||||
list=NULL,
|
||||
} => (result) {
|
||||
// The function used by reduce to join the list into a string.
|
||||
let joiner = func (acc, item) => select (acc.out == ""), NULL, {
|
||||
let joiner = func (acc, item) => select ((acc.out == ""), NULL) => {
|
||||
true = acc{
|
||||
out="@@" % (acc.out,item),
|
||||
},
|
||||
@ -32,7 +32,7 @@ let reverse = func(list) => reduce(func (acc, item) => [item] + acc, [], list);
|
||||
// head returns the first item in a list as a list of one item.
|
||||
// This function is safe for empty list inputs but is not safe
|
||||
// for NULL inputs.
|
||||
let head = func(list) => select len(list) > 0, [], {
|
||||
let head = func(list) => select (len(list) > 0, []) => {
|
||||
true = [list.0],
|
||||
};
|
||||
|
||||
@ -40,7 +40,7 @@ let head = func(list) => select len(list) > 0, [], {
|
||||
// This function is safe for empty lists but is not safe
|
||||
// for NULL inputs.
|
||||
let tail = func(list) => reduce(
|
||||
func (acc, item) => select acc.count > 0, acc{count=1, tail=[]}, {
|
||||
func (acc, item) => select (acc.count > 0, acc{count=1, tail=[]}) => {
|
||||
true = acc{count = acc.count + 1, tail = acc.tail + [item]},
|
||||
},
|
||||
{count=0},
|
||||
@ -81,7 +81,7 @@ let slice = module {
|
||||
|
||||
let list_len = list.len(mod.list);
|
||||
|
||||
let end = select mod.end is "null", mod.end, {
|
||||
let end = select (mod.end is "null", mod.end) => {
|
||||
true = list_len,
|
||||
};
|
||||
|
||||
@ -92,7 +92,7 @@ let slice = module {
|
||||
|
||||
let reducer = func(acc, item) => acc{
|
||||
count = acc.count + 1,
|
||||
list = select (acc.count >= mod.start) && (acc.count <= end), acc.list, {
|
||||
list = select ((acc.count >= mod.start) && (acc.count <= end), acc.list) => {
|
||||
true = acc.list + [item],
|
||||
},
|
||||
};
|
||||
@ -118,7 +118,7 @@ let zip = module{
|
||||
let len2 = len(mod.list2);
|
||||
|
||||
// Compute the min range of the two lists.
|
||||
let rng = select (len1 >= len2), NULL, {
|
||||
let rng = select ((len1 >= len2), NULL) => {
|
||||
true = 0:(len1 - 1),
|
||||
false = 0:(len2 - 1),
|
||||
};
|
||||
|
@ -12,14 +12,14 @@ let base_types = [
|
||||
];
|
||||
|
||||
// Computes the base type of a value.
|
||||
let base_type_of = func (val) => reduce(func (acc, f) => select (acc.val is f), f, {
|
||||
let base_type_of = func (val) => reduce(func (acc, f) => select ((acc.val is f), f) => {
|
||||
true = acc{typ = f},
|
||||
false = acc,
|
||||
}, {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 = func (m, msg) => select m, fail msg, {
|
||||
let must = func (m, msg) => select (m, fail msg) => {
|
||||
true = m,
|
||||
};
|
||||
|
||||
@ -97,13 +97,13 @@ let shaped = module {
|
||||
let simple_handler = func (val, shape) => val is schema.base_type_of(shape);
|
||||
|
||||
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 = this{val=value, shape=acc.shape.(name), partial=mod.partial},
|
||||
},
|
||||
};
|
||||
|
||||
let shape_tuple_handler = func (acc, field_name, value) => acc{
|
||||
ok = select (field_name) in acc.val, false, {
|
||||
ok = select ((field_name) in acc.val, false) => {
|
||||
true = this{val=value, shape=acc.val.(field_name), partial=false},
|
||||
},
|
||||
};
|
||||
@ -118,7 +118,7 @@ let shaped = module {
|
||||
ok = acc.ok && schema.any{val=value, types=acc.shape},
|
||||
};
|
||||
|
||||
let result = select schema.base_type_of(mod.val), false, {
|
||||
let result = select (schema.base_type_of(mod.val), false) => {
|
||||
str = simple_handler(mod.val, mod.shape),
|
||||
int = simple_handler(mod.val, mod.shape),
|
||||
float = simple_handler(mod.val, mod.shape),
|
||||
@ -127,7 +127,7 @@ let shaped = module {
|
||||
tuple = (mod.shape is "tuple") &&
|
||||
match_shape_fields(mod.val, mod.shape) &&
|
||||
match_tuple_fields(mod.val, mod.shape),
|
||||
list = (mod.shape is "list") && select mod.shape == [], true, {
|
||||
list = (mod.shape is "list") && select (mod.shape == [], true) => {
|
||||
false = reduce(list_handler, {shape=mod.shape, ok=true}, mod.val).ok,
|
||||
},
|
||||
func = simple_handler(mod.val, mod.shape),
|
||||
|
@ -48,12 +48,12 @@ let ops = module {
|
||||
let maybe_prefix = check_str.substr{end=split_str.len - 1};
|
||||
let maybe_suffix = check_str.substr{start=split_str.len};
|
||||
|
||||
let result = select maybe_prefix.len == 0, {
|
||||
let result = select (maybe_prefix.len == 0) => {
|
||||
// terminal condition
|
||||
true = mod.acc + [mod.buf],
|
||||
//true = mod,
|
||||
// recurse condition.
|
||||
false = select maybe_prefix.str == mod.sep, {
|
||||
false = select (maybe_prefix.str == mod.sep) => {
|
||||
true = this{ // this is a match to our separator
|
||||
str=maybe_suffix.str,
|
||||
sep=mod.sep,
|
||||
@ -77,10 +77,10 @@ let ops = module {
|
||||
reduce(
|
||||
func(acc, char) => acc{
|
||||
counter = acc.counter + 1,
|
||||
left = select acc.counter < idx, acc.left, {
|
||||
left = select (acc.counter < idx, acc.left) => {
|
||||
true = acc.left + char,
|
||||
},
|
||||
right = select acc.counter >= idx, acc.right, {
|
||||
right = select (acc.counter >= idx, acc.right) => {
|
||||
true = acc.right + char,
|
||||
},
|
||||
},
|
||||
@ -97,7 +97,7 @@ let ops = module {
|
||||
let pkg = mod.pkg();
|
||||
let reducer = func(acc, char) => acc{
|
||||
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) => {
|
||||
true = acc.str + char,
|
||||
},
|
||||
};
|
||||
|
@ -38,7 +38,7 @@ let equal = module{
|
||||
(mod.desc != NULL) || fail "description can't be null";
|
||||
|
||||
let ok = mod.left == mod.right;
|
||||
let desc = select (mod.desc == ""), "@ == @" % (mod.left, mod.right), {
|
||||
let desc = select ((mod.desc == ""), "@ == @" % (mod.left, mod.right)) => {
|
||||
false = mod.desc,
|
||||
};
|
||||
};
|
||||
@ -54,7 +54,7 @@ let not_equal = module{
|
||||
(mod.desc != NULL) || fail "description can't be null";
|
||||
|
||||
let ok = mod.left != mod.right;
|
||||
let desc = select (mod.desc == ""), "@ != @" % (mod.left, mod.right), {
|
||||
let desc = select ((mod.desc == ""), "@ != @" % (mod.left, mod.right)) => {
|
||||
false = mod.desc,
|
||||
};
|
||||
};
|
@ -1,34 +1,34 @@
|
||||
let list = import "std/lists.ucg";
|
||||
let asserts = import "std/testing.ucg";
|
||||
let t = import "std/testing.ucg";
|
||||
|
||||
let list_to_join = [1, 2, 3];
|
||||
|
||||
assert asserts.equal{
|
||||
assert t.equal{
|
||||
left=list.ops{list=list_to_join}.str_join(","),
|
||||
right="1,2,3"
|
||||
};
|
||||
|
||||
assert asserts.equal{
|
||||
assert t.equal{
|
||||
left=list.ops{list=[0, 1, 2, 3]}.len,
|
||||
right=4,
|
||||
};
|
||||
|
||||
assert asserts.equal{
|
||||
assert t.equal{
|
||||
left = list.ops{list=[0, 1, 2, 3]}.reverse().list,
|
||||
right = [3, 2, 1, 0],
|
||||
};
|
||||
|
||||
assert asserts.equal{
|
||||
assert t.equal{
|
||||
left=list.ops{list=["foo", "bar"]}.enumerate().list,
|
||||
right=[[0, "foo"], [1, "bar"]],
|
||||
};
|
||||
|
||||
assert asserts.equal{
|
||||
assert t.equal{
|
||||
left=list.enumerate{start=1, list=["foo", "bar"]},
|
||||
right=[[1, "foo"], [2, "bar"]],
|
||||
};
|
||||
|
||||
assert asserts.equal{
|
||||
assert t.equal{
|
||||
left=list.enumerate{
|
||||
start=1,
|
||||
step=2,
|
||||
@ -37,47 +37,47 @@ assert asserts.equal{
|
||||
right=[[1, "foo"], [3, "bar"]],
|
||||
};
|
||||
|
||||
assert asserts.equal{
|
||||
assert t.equal{
|
||||
left=list.zip{list1=[0, 1], list2=[3, 4]},
|
||||
right=[[0, 3], [1, 4]],
|
||||
};
|
||||
|
||||
assert asserts.equal{
|
||||
assert t.equal{
|
||||
left=list.tail([0,1,2,3,4]),
|
||||
right=[1,2,3,4],
|
||||
};
|
||||
|
||||
assert asserts.equal{
|
||||
assert t.equal{
|
||||
left=list.ops{list=[0,1,2,3,4]}.head(),
|
||||
right=[0],
|
||||
};
|
||||
|
||||
assert asserts.equal{
|
||||
assert t.equal{
|
||||
left=list.ops{list=[0,1,2,3,4]}.tail().list,
|
||||
right=[1,2,3,4],
|
||||
};
|
||||
|
||||
assert asserts.equal{
|
||||
assert t.equal{
|
||||
left=list.slice{end=2, list=[0,1,2,3]},
|
||||
right=[0,1,2],
|
||||
};
|
||||
|
||||
assert asserts.equal{
|
||||
assert t.equal{
|
||||
left=list.slice{list=[0,1,2,3]},
|
||||
right=[0,1,2,3],
|
||||
};
|
||||
|
||||
assert asserts.equal{
|
||||
assert t.equal{
|
||||
left=list.slice{end=0, list=[0,1,2,3]},
|
||||
right=[0],
|
||||
};
|
||||
|
||||
assert asserts.equal{
|
||||
assert t.equal{
|
||||
left=list.slice{list=[]},
|
||||
right=[],
|
||||
};
|
||||
|
||||
assert asserts.equal{
|
||||
assert t.equal{
|
||||
left=list.slice{list=[0]},
|
||||
right=[0],
|
||||
};
|
@ -1,54 +1,54 @@
|
||||
let strings = import "std/strings.ucg";
|
||||
let asserts = import "std/testing.ucg";
|
||||
let t = import "std/testing.ucg";
|
||||
|
||||
let str_class = strings.ops{str="foo bar"};
|
||||
|
||||
assert asserts.equal{
|
||||
assert t.equal{
|
||||
left = str_class.split_on{},
|
||||
right = ["foo", "bar"],
|
||||
};
|
||||
|
||||
assert asserts.equal{
|
||||
assert t.equal{
|
||||
left = strings.ops{str="foo"}.split_on{},
|
||||
right = ["foo"],
|
||||
};
|
||||
|
||||
assert asserts.equal{
|
||||
assert t.equal{
|
||||
left = strings.ops{str=""}.split_on{},
|
||||
right = [""],
|
||||
};
|
||||
|
||||
assert asserts.equal{
|
||||
assert t.equal{
|
||||
left = strings.ops{str="foo=>bar=>quux"}.split_on{on="=>"},
|
||||
right = ["foo", "bar", "quux"],
|
||||
};
|
||||
|
||||
assert asserts.equal{
|
||||
assert t.equal{
|
||||
left = str_class.split_at(3),
|
||||
right = {left="foo", right=" bar"},
|
||||
};
|
||||
|
||||
assert asserts.equal{
|
||||
assert t.equal{
|
||||
left = str_class.len,
|
||||
right = 7,
|
||||
};
|
||||
|
||||
assert asserts.equal{
|
||||
assert t.equal{
|
||||
left = str_class.chars,
|
||||
right = ["f", "o", "o", " ", "b", "a", "r"],
|
||||
};
|
||||
|
||||
assert asserts.equal{
|
||||
assert t.equal{
|
||||
left = str_class.substr{start=1}.str,
|
||||
right = "oo bar",
|
||||
};
|
||||
|
||||
assert asserts.equal{
|
||||
assert t.equal{
|
||||
left = str_class.substr{end=5}.str,
|
||||
right = "foo ba",
|
||||
};
|
||||
|
||||
assert asserts.equal{
|
||||
assert t.equal{
|
||||
left = str_class.substr{end=8}.str,
|
||||
right = "foo bar",
|
||||
};
|
@ -1,67 +1,67 @@
|
||||
let asserts = import "std/testing.ucg";
|
||||
let t = import "std/testing.ucg";
|
||||
|
||||
let not_equal_result = asserts.not_equal{
|
||||
let not_equal_result = t.not_equal{
|
||||
left=1,
|
||||
right=2,
|
||||
};
|
||||
assert not_equal_result;
|
||||
assert asserts.equal{
|
||||
assert t.equal{
|
||||
left=not_equal_result.desc,
|
||||
right="1 != 2",
|
||||
};
|
||||
|
||||
let bad_not_equal_result = asserts.not_equal{
|
||||
let bad_not_equal_result = t.not_equal{
|
||||
left=1,
|
||||
right=1,
|
||||
};
|
||||
assert asserts.not_ok{test=bad_not_equal_result.ok};
|
||||
assert asserts.equal{
|
||||
assert t.not_ok{test=bad_not_equal_result.ok};
|
||||
assert t.equal{
|
||||
left=bad_not_equal_result.desc,
|
||||
right="1 != 1",
|
||||
};
|
||||
|
||||
|
||||
let equal_result = asserts.equal{
|
||||
let equal_result = t.equal{
|
||||
left=1,
|
||||
right=1,
|
||||
};
|
||||
assert equal_result;
|
||||
assert asserts.equal{
|
||||
assert t.equal{
|
||||
left=equal_result.desc,
|
||||
right="1 == 1",
|
||||
};
|
||||
|
||||
let bad_equal_result = asserts.equal{
|
||||
let bad_equal_result = t.equal{
|
||||
left=1,
|
||||
right=2,
|
||||
};
|
||||
assert asserts.equal{
|
||||
assert t.equal{
|
||||
left=bad_equal_result.desc,
|
||||
right="1 == 2",
|
||||
};
|
||||
|
||||
let ok_result = asserts.ok{
|
||||
let ok_result = t.ok{
|
||||
test=true,
|
||||
};
|
||||
assert ok_result;
|
||||
assert asserts.equal{
|
||||
assert t.equal{
|
||||
left=ok_result.desc,
|
||||
right="TODO description",
|
||||
};
|
||||
|
||||
let bad_ok_result = asserts.ok{
|
||||
let bad_ok_result = t.ok{
|
||||
test=false,
|
||||
};
|
||||
assert asserts.equal{
|
||||
assert t.equal{
|
||||
left=bad_ok_result.desc,
|
||||
right="TODO description",
|
||||
};
|
||||
|
||||
let not_ok_result = asserts.not_ok{
|
||||
let not_ok_result = t.not_ok{
|
||||
test=false,
|
||||
};
|
||||
assert not_ok_result;
|
||||
assert asserts.equal{
|
||||
assert t.equal{
|
||||
left=not_ok_result.desc,
|
||||
right="TODO description",
|
||||
};
|
@ -1,5 +1,5 @@
|
||||
// Assert that a value is a tuple. Generate a compile failure if it is not.
|
||||
let assert_tuple = func (tpl) => select tpl is "tuple", NULL, {
|
||||
let assert_tuple = func (tpl) => select (tpl is "tuple", NULL) => {
|
||||
false = fail "@ is not a tuple" % (tpl),
|
||||
};
|
||||
|
||||
@ -91,12 +91,12 @@ let field_type = module{
|
||||
pkg.assert_tuple(mod.tpl);
|
||||
|
||||
// Next we assert that mod.field is a string.
|
||||
select mod.field is "str", NULL, {
|
||||
select (mod.field is "str", NULL) => {
|
||||
false = fail "@ is not a string" % (mod.field),
|
||||
};
|
||||
|
||||
// and finally that mod.type is a string
|
||||
select mod.type is "str", NULL, {
|
||||
select (mod.type is "str", NULL) => {
|
||||
false = fail "@ is not a string" % (mod.type),
|
||||
};
|
||||
|
||||
@ -104,7 +104,7 @@ let field_type = module{
|
||||
let it = pkg.iter{tpl=mod.tpl};
|
||||
|
||||
// The reducer function used to check the field's types if it exists.
|
||||
let reducer = func (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
|
||||
});
|
||||
|
@ -6,7 +6,7 @@ let validate_ns = func(ns) => schema.any{val=ns, types=["", {prefix="", uri=""}]
|
||||
|
||||
// Constructs an xml namespace for use in an xml tag or document root.
|
||||
// Use NULL for the uri argument to use just the prefix.
|
||||
let ns = func(prefix, uri) => select uri != NULL, {
|
||||
let ns = func(prefix, uri) => select (uri != NULL) => {
|
||||
true = {
|
||||
prefix = prefix,
|
||||
uri = uri,
|
||||
@ -30,9 +30,9 @@ let tag = module{
|
||||
children = mod.children,
|
||||
};
|
||||
|
||||
let result = select mod.ns == NULL, {
|
||||
let result = select (mod.ns == NULL) => {
|
||||
true = base,
|
||||
false = select pkg.validate_ns(mod.ns), {
|
||||
false = select (pkg.validate_ns(mod.ns)) => {
|
||||
true = base{ns=mod.ns},
|
||||
false = fail "XML Tag namespaces must be a string or tuple of {prefix=, uri=} but is @" % (mod.ns),
|
||||
},
|
||||
@ -49,7 +49,7 @@ let validate_node = func(node) => schema.any{val=node, types=["", {name = ""}],
|
||||
//
|
||||
// The root node must be a valid xml node. Either a text or an
|
||||
// xml node.
|
||||
let doc = func(root) => select validate_node(root), {
|
||||
let doc = func(root) => select (validate_node(root)) => {
|
||||
true = {
|
||||
root = root,
|
||||
},
|
||||
|
Loading…
x
Reference in New Issue
Block a user