mighty

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

commit 031ebf5c6b52a47d3b98184b2a82c5c955d5b5ea
Author: keyle <keyle@capsule.org>
Date:   Sat, 16 May 2026 12:03:23 +1000

init

Diffstat:
Alanguage2.bnf | 68++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Alanguage2.mty | 45+++++++++++++++++++++++++++++++++++++++++++++
Anotes.md | 90+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 203 insertions(+), 0 deletions(-)

diff --git a/language2.bnf b/language2.bnf @@ -0,0 +1,68 @@ +# Mighty language2 sketch grammar +# Layout produces INDENT/DEDENT after `::`. + +program ::= { top } +top ::= namespace | use | struct | function + +namespace ::= "ns" path +use ::= "use" path + +struct ::= "struct" Type "::" block(member) +member ::= field | function +field ::= type names +names ::= name { "," name } + +function ::= { pre } signature { where } body +pre ::= "pre" expr +where ::= "where" expr # may mention contextual `result` +signature ::= type name "(" [ params ] ")" +params ::= param { "," param } +param ::= type [ name ] +body ::= "=" expr | "::" block(stmt) + +stmt ::= binding | ret | expr +binding ::= type name "=" expr +ret ::= "ret" expr + +type ::= path { "[]" } +path ::= name { "." name } + +expr ::= conditional +conditional ::= pipe [ "if" expr "else" expr ] +pipe ::= reduce { "|" ( map | expr ) } +map ::= "@" "(" expr ")" # each: `.` is the current element +reduce ::= [ op "/" ] logic # +/xs, */xs, max/xs + +logic ::= compare { ( "and" | "or" ) compare } +compare ::= range { cmp range } +range ::= add [ ".." add ] +add ::= mul { ( "+" | "-" ) mul } +mul ::= pow { ( "*" | "/" ) pow } +pow ::= unary { "^" unary } +unary ::= [ "-" | "#" ] postfix # #xs is length/count + +postfix ::= atom { call | selector | "." name } +call ::= "(" [ args ] ")" +args ::= expr { "," expr } +selector ::= "[" [ selectors ] "]" # index, gather, mask, or filter expr +selectors ::= expr { [ "," ] expr } + +atom ::= literal | path | subject | array | "(" expr ")" +subject ::= "." [ name ] # current subject/self/element +array ::= "[" [ selectors ] "]" + +literal ::= int | float | string | "true" | "false" +op ::= "+" | "*" | "&" | "|" | "min" | "max" | name +cmp ::= "==" | "!=" | "<" | "<=" | ">" | ">=" + +block(x) ::= INDENT { x } DEDENT + +# Selector semantics: +# xs[i] scalar index +# xs[is] gather by int[] indices +# xs[mask] compress by bool[] mask +# xs[.valid] filter by expression evaluated per element + +# `.` semantics: +# In methods, `.` is the receiver. In free functions, `.` is the first argument. +# In selectors and @(...), `.` is the current element. diff --git a/language2.mty b/language2.mty @@ -0,0 +1,45 @@ +ns app + +use io +use math + +struct Vec2 :: + float x + float y + + float len() where result >= 0.0 = + math.sqrt(.x ^ 2 + .y ^ 2) + + int clamp(int x, int lo, int hi) + where lo <= hi + where result >= lo and result <= hi + = + min(max(x, lo), hi) + +struct Reading :: + int sensor + float value + bool valid + + bool usable() = + .valid and .value >= 0.0; + + str label() = + "high" if .value > 100.0 else "normal" + +pre #xs > 0 +float mean(float[] xs) = +/xs / #xs + + +float[] values(Reading[] rows) = + rows[.usable()] + | @(.value) + + +int main() :: + Reading[] rows = load_readings("readings.csv") + float[] xs = values(rows) + + io.put("mean = " + str(mean(xs))) + ret 0 + diff --git a/notes.md b/notes.md @@ -0,0 +1,90 @@ + +@(expr) +------- + +Evaluate `expr` once per element, with . bound to the current element. + +``` +Examples: + +int[] doubled(int[] xs) = + xs | @(. * 2) + +str[] labels(Reading[] rows) = + rows | @("high" if .value > 100.0 else "normal") +``` + +Masking or filtering +--------------------- + +Masking/filtering works as you would expect at first, then evolves into something more like APL. + +It's best to call `[]` the Selector. + +``` +xs[i] // scalar index +xs[is] // gather by int[] indices +xs[mask] // compress by bool[] mask +``` + +`xs[3]` returns the 4th element +`xs[[0 2]]` returns the first and 3rd element +`xs[0..-1]` returns the range from the 1st, to the one before last +`xs[[true, false, true]]` returns the mask against the collection, in this case 1st and 3rd. + + +Selectors can also be using expression to filter collections + +`integer_list[. > 0]` returns values higher than 0 +`rows[.valid]` within a struct, invoke valid(element) on each element + +Implied self +------------ + +`.` is `self` within the context, it's the current subject. + +Inside a free function it's implied the first argument. + +`float len(Vec2) = math.sqrt(.x ^ 2 + .y ^ 2)` + +is equivalent to + +`float len(Vec2 v) = math.sqrt(v.x ^ 2 + v.y ^2)` + +inside a method of a struct, it's implied to this struct subject + +``` +struct Vec2 :: + float x, y + float len() = math.sqrt(.x ^ 2 + .y ^2) +``` + +Inside a selector, map, or other collection expr, `.` refers to the current element. + +`rows[valid]` + + + + + + + + + + + + + + + + + + + + + + + + + +