commit 08ed12b28e86d03ca63b25cc6cfd876a7fd481b3
parent 031ebf5c6b52a47d3b98184b2a82c5c955d5b5ea
Author: keyle <keyle@capsule.org>
Date: Sat, 16 May 2026 12:05:09 +1000
old
Diffstat:
| A | old/old-language.bnf | | | 335 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| A | old/old-language.mty | | | 134 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
2 files changed, 469 insertions(+), 0 deletions(-)
diff --git a/old/old-language.bnf b/old/old-language.bnf
@@ -0,0 +1,335 @@
+---------- plan
+
+5 scalar types: int float bool char str
+arrays: T[]
+structs
+enums
+methods
+contracts: @pre @post @inv
+expression functions with =
+block functions with ::
+match
+conditional expression: x if cond else y
+pipes: | f, | f(args), | [pred], | @(mapper)
+
+drop for now:
+
+block if/else
+fixed-shape arrays
+implicit whitespace arrays
+bind-pipe
+mutating methods
+function overloading
+standalone attributes
+same-line block bodies
+complex # shape semantics
+
+note: pipe rules:
+x | f // f(x)
+x | f(a, b) // f(x, a, b)
+x | [pred] // filter(x, pred)
+x | @(mapper) // map(x, mapper)
+
+
+
+
+------------------ ebnf
+
+
+
+
+:: opens a layout block
+indent enters the block
+dedent exits the block
+newline separates statements
+; only separates statements on one line
+
+= opens to a single expr line
+
+note: the following is wrong about this
+
+
+
+
+program = { top_decl } EOF ;
+
+top_decl = mod_decl
+ | use_decl
+ | type_decl
+ | const_decl
+ | func_decl ;
+
+mod_decl = "mod" path CLOSE ;
+use_decl = "use" path CLOSE ;
+
+path = ident { "." ident } ;
+
+attr_decl = attr { NEWLINE attr } ;
+attr = "@" ident expr ;
+
+const_decl = "const" type ident "=" expr CLOSE ;
+
+func_decl = { attr NEWLINE }
+ type ident "(" [ params ] ")" func_body ;
+
+func_body = "=" expr CLOSE
+ | "::" block ;
+
+params = param { "," param } ;
+param = [ "mut" ] type ident
+ | [ "mut" ] "self" ;
+
+type = base_type { array_suffix } ;
+
+base_type = "int"
+ | "float"
+ | "bool"
+ | "char"
+ | "str"
+ | ident ;
+
+array_suffix = "[]" ;
+shape = int_lit { "," int_lit } ;
+
+
+
+
+
+
+
+
+block = NEWLINE INDENT block_body DEDENT ;
+
+block_body = { stmt stmt_sep } final_expr CLOSE ;
+
+stmt_sep = NEWLINE | SEP ;
+
+stmt = var_decl
+ | assign_stmt
+ | defer_stmt
+ | expr ;
+
+var_decl = [ "mut" ] type ident "=" expr ;
+
+assign_stmt = lvalue "=" expr ;
+
+defer_stmt = "defer" expr ;
+
+final_expr = expr ;
+
+lvalue = ident
+ | postfix_expr "." ident
+ | postfix_expr "[" expr "]" ;
+
+
+
+
+
+
+
+
+int main() ::
+ io.put("hello")
+ 0;
+// becomes
+func_decl
+ block
+ stmt: io.put("hello")
+ final_expr: 0
+ CLOSE
+
+
+
+
+
+
+
+
+
+
+
+type_decl = "type" ident "=" type_body CLOSE ;
+
+type_body = struct_type
+ | enum_type
+ | type ;
+
+struct_type = "struct" "::" NEWLINE INDENT
+ { struct_item }
+ DEDENT ;
+
+struct_item = field_decl
+ | method_decl
+ | attr_decl ;
+
+field_decl = type ident stmt_sep ;
+
+method_decl = { attr NEWLINE }
+ type ident "(" [ params ] ")" func_body ;
+
+enum_type = "enum" "::" NEWLINE INDENT
+ { enum_item }
+ DEDENT ;
+
+enum_item = enum_case stmt_sep
+ | method_decl
+ | attr_decl ;
+
+enum_case = ident [ "(" [ fields ] ")" ] ;
+
+fields = field { "," field } ;
+field = type ident ;
+
+
+
+
+
+
+
+
+primary
+postfix: call, index, field
+prefix: -, !, #, +/, */, min/, max/, avg/
+power: ^
+multiplicative: *, /, %
+additive: +, -
+range: ..
+comparison: == != < <= > >=
+logical and
+logical or
+pipe: |
+lambda: =>
+
+
+
+
+
+
+ebnf
+
+
+expr = lambda_expr ;
+
+lambda_expr = pipe_expr
+ | ident "=>" expr ;
+
+pipe_expr = logic_or_expr { "|" pipe_stage } ;
+
+pipe_stage = "[" expr "]" (* filter: x | [pred] *)
+ | "@(" expr ")" (* map: x | @(f) *)
+ | ident "=>" expr (* bind: x | y => expr *)
+ | "." ident "(" [ args ] ")" (* method: x | .len() *)
+ | postfix_expr ; (* call: x | f or x | f(a) *)
+
+logic_or_expr = logic_and_expr { "or" logic_and_expr } ;
+
+logic_and_expr = compare_expr { "and" compare_expr } ;
+
+compare_expr = range_expr { compare_op range_expr } ;
+
+compare_op = "==" | "!=" | "<" | "<=" | ">" | ">=" ;
+
+range_expr = add_expr [ ".." add_expr ] ;
+
+add_expr = mul_expr { add_op mul_expr } ;
+add_op = "+" | "-" ;
+
+mul_expr = power_expr { mul_op power_expr } ;
+mul_op = "*" | "/" | "%" ;
+
+power_expr = prefix_expr [ "^" power_expr ] ;
+
+prefix_expr = prefix_op prefix_expr
+ | postfix_expr ;
+
+prefix_op = "-"
+ | "!"
+ | "#"
+ | "+/"
+ | "*/"
+ | "min/"
+ | "max/"
+ | "avg/" ;
+
+postfix_expr = primary_expr { postfix_suffix } ;
+
+postfix_suffix = call_suffix
+ | index_suffix
+ | field_suffix ;
+
+call_suffix = "(" [ args ] ")" ;
+args = expr { "," expr } ;
+
+index_suffix = "[" index_expr "]" ;
+index_expr = expr
+ | [ expr ] ".." [ expr ] ;
+
+field_suffix = "." ident ;
+
+primary_expr = literal
+ | ident
+ | array_lit
+ | if_expr
+ | match_expr
+ | "(" expr ")" ;
+
+
+
+
+
+
+
+
+
+expr = lambda_expr ;
+
+lambda_expr = if_expr
+ | ident "=>" expr ;
+
+if_expr = pipe_expr [ "if" expr "else" if_expr ] ;
+
+
+
+
+
+
+
+
+
+
+
+literal = int_lit
+ | float_lit
+ | bool_lit
+ | char_lit
+ | str_lit ;
+
+bool_lit = "true" | "false" ;
+
+array_lit = "[" [ expr { "," expr } ] "]"
+ | scalar_run ;
+
+scalar_run = scalar_atom scalar_atom { scalar_atom } ;
+
+scalar_atom = int_lit
+ | float_lit
+ | bool_lit
+ | char_lit
+ | str_lit ;
+
+ident = letter { letter | digit | "_" } ;
+
+int_lit = digit { digit } ;
+float_lit = digit { digit } "." digit { digit } ;
+
+char_lit = "'" char_body "'" ;
+str_lit = '"' { str_char } '"' ;
+
+
+
+
+
+
+
+
+
diff --git a/old/old-language.mty b/old/old-language.mty
@@ -0,0 +1,134 @@
+ns main;
+
+from namespace use stream_data;
+
+let Point :: x:f, y:f;
+
+let Player :: {
+ pos:Point;
+ health:f;
+ age:i;
+ fx distance : Player -> (f, f) :: (abs(Player.pos.x - pos.x), abs(Player.pos.y - pos.y));
+}
+
+fx distance p1:Player, p2:Player -> f, f ::
+ (abs(p1.pos.x - p2.pos.x), abs(p1.pos.y - p2.pos.y));
+
+pub dupe :: (str, int) = (*)
+
+let Player :: struct {
+ Point pos;
+ dec health;
+ int age;
+ bool alive;
+ pub is_old = age > 60;
+}
+
+let RSVP :: enum(str) {
+
+}
+
+
+enum(str) RSVP :: YES, NO;
+
+pub struct Person ::
+ str name,
+ str domain,
+ int age,
+ dec size,
+ Bool alive,
+ RSVP invited,
+ fx is_alive :: -> bool = .alive,
+ fn email :: -> str = "$name@${domain}",
+ fx knows :: Person p -> bool = .in_contact_with(p);
+
+
+fx new_external_person :: str name -> Person = Person(name: name, alive: true);
+
+
+fx(Float, Float) distance(Point a, b) :: (abs(a.x - b.x), abs(a.y - b.y))
+
+fx distance :: Point a, b -> Float, Float = (abs(a.x - b.x), abs(a.y - b.y));
+
+
+let Person :: struct = str name, int age, dec size, bool alive, RSVP invite;
+
+fx in_space :: char c -> bool = (c == ' ' || c == '\r' || c == '\n' || c == '\t');
+
+fx rev :: str x -> str = x[.. by -1];
+
+fx trim :: str x -> str = x
+ | x[drop while in_space]
+ | rev
+ | x[drop while in_space]
+ | rev;
+
+
+fx say_hello() :: printf("hello\n")
+
+
+fx distance(Point a, b) ::
+ (abs(a.x - b.x), abs(a.y - b.y))
+
+fx distance(Point a, b -> (dec, dec))
+
+fx is_even(ref int -> bool) = (% 2 == 0)
+
+
+fx distance(Point a, b) -> (f, f) = (abs(a.x - b.x), abs(a.y - b.y))
+
+----------
+
+fx distance(a:pos, b:pos) (f, f) = (abs(a.x - b.x), abs(a.y - b.y))
+
+let Player = {
+ pos:Point,
+ health:f,
+ age:i,
+ alive:b = true
+ fx distance :: fx(p2:Player) (f, f) = (abs(pos.x - p2.pos.x), abs(pos.y - p2.pos.y))
+}
+
+let even : i -> b :: % 2 == 0
+
+let add : i, i -> i :: +
+
+let add_mult_by_5 : i, i -> i :: + * 5
+
+let add_mult_by_6 : a:i, b:i -> i :: (a + b) * 6
+
+fx add_mult_by_x (a:i, b:i, x:i) i = (a + b) * x
+
+from libc use printf[ffi]
+
+fx say_hello :: printf("hello\n")
+
+fx say_hello = printf("hello\n")
+
+
+fx rev(text:s) -> s = text[.. by -1];
+
+
+
+fx rev :
+ s -> s = s[.. by -1]
+
+fn is_space : c -> b =
+ c == ' ' || c == '\r' || c == '\n' || c == '\t';
+
+fx trim(text:s) -> s =
+ len(text) == 0 ? text :
+ text
+ | t => t[drop while is_space]
+ | rev
+ | t => t[drop while is_space]
+ | rev;
+
+is_space :: c -> b = c == ' ' || c == '\r' || c == '\n' || c == '\t';
+
+
+pub let is_space : c -> b = (c == ' ' || c == '\r' || c == '\n' || c == '\t');
+
+is_space :: char c -> bool =
+
+