Skip to content

Latest commit

 

History

History
146 lines (112 loc) · 4.28 KB

Semantics.md

File metadata and controls

146 lines (112 loc) · 4.28 KB

Semantics

Basic

TreeScript programs are made up of statements. A statement is a reducer or group. A reducer transforms one AST expression into another.

c’println(\str)’: js’console.log(\str)’;

A group organizes other statements.

&Print[];

&Print[].
——-
c’print(\str)’: js’out += \str’;
c’println(\str)’: js’out += \str + “\n”’;
c’fprint(stderr, \str)’: js’err += \str’;
c’fprintln(stderr, \str)’: js’err += \str’;

When a value enters a group with an evaluation context sub-statement, and none of its statements match it, it’s sub-statements will transform nested expressions, based on the context reducer.

&Arith1[].
——-
hs’\x + \y’: hs’(+) \x \y’;
E[hs’(\x)’]: hs’(\(E[\x]))’;

hs’(3 + 4)’ => hs’((+) 3 4)’;
&Arith1[].
——-
hs’\x + \y’: hs’(+) \x \y’;
E[&Rec[]];

&Rec[].
——-
E[hs’\x \y \z’]: hs’\(E[\x]) \(E[\y]) \(E[\z])’;
E[hs’(\x)’]: hs’(\(E[\x]))’;

hs’(mod (49) ((3 + 4)))’ => hs’(mod (49) (((+) 3 4)))’;

When an AST enters a program or group defined with ——-, every sub-statement, in sequence, transforms it once. When an AST enters a group defined with ===, and one of its sub-statements matches it, the AST goes back to the start and the entire group tries to transform it again.

&Arith1[].
——-
hs’\x + \y’: hs’(+) \x \y’;
hs’\x - \y’: hs’(-) \x \y’;
E[&Rec[]];

&Rec[].
——-
E[hs’\x \y \z’]: hs’\(E[\x]) \(E[\y]) \(E[\z])’;
E[hs’(\x)’]: hs’(\(E[\x]))’;

hs’(2 - 5) + (3 + 4)’ => hs’(+) (2 - 5) (3 + 4)’;
&Arith1[].
===
hs’\x + \y’: hs’(+) \x \y’;
hs’\x - \y’: hs’(-) \x \y’;
E[&Rec[]];

&Rec[].
——-
E[hs’\x \y \z’]: hs’\(E[\x]) \(E[\y]) \(E[\z])’;
E[hs’(\x)’]: hs’(\(E[\x]))’;

hs’(2 - 5) + (3 + 4)’ => hs’(+) ((-) 2 5) ((+) 3 4)’;

A function performs an operation such as arithmetic or a symbol lookup. Functions come from [[Libraries]], the functions which are available depend on the libraries which are locally installed.

c’\(C_Number[\x])’ + \(C_Number[\y])’: C_Number[#Base_Add[\x; \y]];

c’3 + 4’: c’7’;

When a reducer matches and transforms an expression, if there are any groups immediately after its output, they’ll further transform the expression.

TODO Subst example

When a reducer’s input matches an expression, if there are any groups immediately after, they’ll guard the expression. If one of the guards fails, the expression won’t be transformed.

js’\xs.forEach(\f)’ &Func[]: js’for (\x in \xs) \body’;

&Func[].
——-
#Js_Lookup[\f]: js’function(\x) \body’;

js’
var add3 = function(n) { console.log(n + 3); };
[2, 5, 7].forEach(add3);
‘ => js’
for (n in [2, 5, 7]) {
  console.log(n + 3);
}
‘;

Transformation and Guarding

When a reducer transforms an AST expression, it tries to match the expression against its input (left) value. If it matches, each associated input group guards the expression. If all guards succeed, the reducer successfully transforms the expression - it replaces it with its output (right) value, then applies associated output guards.

An expression matches an input it equals the input, except for binds (e.g. \foo, \). Binds can match any expression, except if multiple named binds have the same name, they must all match the same expression. Once an expression matches, the binds are “filled” with the corresponding sub-expressions - they’re substituted in output values and associated groups.

Foo[Bar[\foo]; Baz[\foo]; \; \]
//Matches
Foo[Bar[Baz[5]]; Baz[Baz[5]]; 7; 8]
Foo[Bar[Baz[5]]; Baz[Baz[5]]; Baz[5]; 9]
//Doesn’t match
Foo[Bar[Baz[5]]; Baz[Qux[]]; 7]
Foo[Baz[5]; Baz[5]; 7]

Complex guard example:

hs’\x \infix \y’ &Env[]: hs’\postfix \x \y’;

&Env[].
——-
\x: &GetFixity[]: Postfix[\];
\infix &GetFixity[]: Infix[\postfix];

&GetFixity[].
——-
hs’+’: Infix[hs’(+)’];
hs’-’: Infix[hs’(-)’];
hs’*’: Infix[hs’(*)’];
hs’/’: Infix[hs’(/)’];
hs’`\x`’: Infix[hs’\(Haskell_Symbol[\x])’];
Haskell_Symbol[\x]: Postfix[hs’`\x`’];
\_: Postfix[Null[]];