From: cassowarii Date: Tue, 14 Jul 2026 20:55:25 +0000 (-0700) Subject: minor syntax tweaks X-Git-Url: https://www.git.cassowary.me/gitweb.cgi?a=commitdiff_plain;h=d3505c7e0c1f02943a42c7526e0f74e33666f3c6;p=sarabande.git minor syntax tweaks --- diff --git a/sample/generator.sbd b/sample/generator.sbd index 0687f95..f06aa0b 100644 --- a/sample/generator.sbd +++ b/sample/generator.sbd @@ -1,5 +1,7 @@ let generator = (=> { let instance_methods = { + next: => f { f }, + filter: => f { => pred { generator => { @@ -49,16 +51,49 @@ let generator = (=> { if ended { last = make_next(last) } + last } } }, + continue2: => f { + => make_next { + let last1 = nil + let last2 = nil + let ended = false + generator => { + if not ended { + let this_one = f() + if this_one != nil { + last1 = last2 + last2 = this_one + } else { + ended = true + } + } + + if ended { + let this_one = nil + if last1 != nil and last2 != nil { + this_one = make_next(last1, last2) + } + last1 = last2 + last2 = this_one + } + + last2 + } + } + }, + upuntil: => f { => cond { generator => { let result = f() - if result == nil or cond result { + if result == nil { + nil + } else if cond result { nil } else { result @@ -67,6 +102,26 @@ let generator = (=> { } }, + each: => f { + => callback { + generator => { + let result = f() + callback(result) unless result == nil + result + } + } + }, + + empty?: => f { + f() == nil + }, + + run: => f { + repeat { + let result = f() + } until result == nil + }, + reduce: => f { => init, combine { let value = init @@ -77,19 +132,14 @@ let generator = (=> { value } }, - - each: => f { - => callback { - repeat { - let result = f() - callback(result) unless result == nil - } while result != nil - } - }, } let class_methods = { of: => ...list { + generator::from_list list + }, + + from_list: => list { let index = 0 generator => { if index >= list.length { @@ -108,21 +158,68 @@ let generator = (=> { class_methods(op::index) } else { => method { - if method == :next { - f - } else { - instance_methods[method](f) - } + instance_methods[method](f) } } } })() -let sum_odd_squares_under_1_000_000 = generator::of(1) - .continue(=> a { a + 1 }) - .map(=> a { a * a }) - .filter(=> a { not a %% 2 }) - .upuntil(=> a { a >= 1_000_000 }) - .reduce(0, => a, b { a + b }) +# project euler 0 +println ( + list::iota1 130_000 + .filter => n { not (n %% 2) } + .map => n { n * n } + .reduce 0, => a, b { a + b } +) -println sum_odd_squares_under_1_000_000 +# project euler 1 +println ( + generator::of 1 + .continue => a { a + 1 } + .upuntil => a { a >= 1000 } + .filter => num { [3, 5].any? => factor { num %% factor } } + .reduce 0, => a, b { a + b } +) + +# project euler 2 +println ( + generator::from_list [0, 1] + .continue2 => a, b { a + b } + .upuntil => a { a >= 40_000_000 } + .filter => a { a %% 2 } + .reduce(0, => a, b { a + b }) +) + +# project euler 3 +def factors num { + generator::of 2 + .continue => a { a + 1 } + .upuntil => a { a >= math::sqrt num } + .filter => a { num %% a } +} + +println ( + factors 600851475143 + .filter(=> a { factors(a).empty? }) + .reduce(0, math::max) +) + +# project euler 4 +def is_palindrome num { + string::from num | _ == _.split().reverse().join() +} + +println ( + generator::of 999 + .continue => a { a - 1 } + .upuntil => a { a < 100 } + .map => a { + generator::of 999 + .continue => b { b - 1 } + .upuntil => b { b < 100 } + .map => b { a * b } + .filter => p { is_palindrome p } + .reduce 0, math::max + } + .reduce 0, math::max +) diff --git a/src/parse/lexer.c b/src/parse/lexer.c index be57d9e..47d8c0f 100644 --- a/src/parse/lexer.c +++ b/src/parse/lexer.c @@ -144,7 +144,10 @@ static flag insert_semicolon_after(sbTokenType type) { static flag cancel_semicolon_before(sbTokenType type) { return type == T_DOT - || type == T_PIPE; + || type == T_PIPE + || type == T_RPAREN + || type == T_RBRACKET + || type == T_RBRACE; } /* identifier + space + one of these gets a ( inserted */ diff --git a/src/parse/parser.c b/src/parse/parser.c index 897d6a3..e7535ed 100644 --- a/src/parse/parser.c +++ b/src/parse/parser.c @@ -250,7 +250,14 @@ static void fprint_left_error_margin(FILE *out, usize line_num) { static sbAst syntax_error(hParser pr) { if (pr->error_state) return ERROR_NODE; - sbLexToken unexpected_token = peek_ahead(pr, 0); + i32 peek_amount = 0; + sbLexToken unexpected_token; + do { + /* find first non-invisible token to report error */ + unexpected_token = peek_ahead(pr, peek_amount); + peek_amount ++; + } while (unexpected_token.invisible); + if (unexpected_token.type == T_ERROR) { fprintf(stderr, "syntax error: invalid character"); } else if (unexpected_token.type == T_WRONGBRACKET) { @@ -492,8 +499,10 @@ static sbAst parse_inside_hash(hParser pr) { do { sbAst key = parse_hash_key(pr); - if (key == NO_NODE) break; - if (!expect(pr, ':')) return syntax_error(pr); + if (!expect(pr, ':')) { + if (key == NO_NODE) break; + return syntax_error(pr); + } sbAst value = parse_expr(pr, 0); *put_here = seq_node(pr, AST_NODE_NEXT, seq_node(pr, AST_NODE_HASHENTRY, key, value), NO_NODE); diff --git a/src/vm/operations.c b/src/vm/operations.c index 507ae37..a22c3f7 100644 --- a/src/vm/operations.c +++ b/src/vm/operations.c @@ -91,7 +91,7 @@ hV sbV_lt(const hV *a, const hV *b) { return HVBOOL(a->float_val < b->float_val); } } else { - PANIC("todo"); + PANIC("todo %lld", (long long)a->type); } }