mighty

The mighty programming language, compiler and tools (WIP)
Log | Files | Refs

commit 08ed12b28e86d03ca63b25cc6cfd876a7fd481b3
parent 031ebf5c6b52a47d3b98184b2a82c5c955d5b5ea
Author: keyle <keyle@capsule.org>
Date:   Sat, 16 May 2026 12:05:09 +1000

old

Diffstat:
Aold/old-language.bnf | 335+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aold/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 = + +