From ddff3e48e82eea5c2f4fab6d1c925ad17c499e1e Mon Sep 17 00:00:00 2001 From: Ian Piumarta Date: Thu, 9 May 2024 13:38:47 +0900 Subject: [PATCH] Add "let name = value, ... ;" to create local variables. --- minproto.leg | 56 +++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 51 insertions(+), 5 deletions(-) diff --git a/minproto.leg b/minproto.leg index 669f362..8de41cd 100644 --- a/minproto.leg +++ b/minproto.leg @@ -1,6 +1,6 @@ # minproto.leg -- minimal prototype langauge for semantic experiments # -# last edited: 2024-05-09 10:17:11 by piumarta on zora-1034.local +# last edited: 2024-05-09 11:30:35 by piumarta on zora-1034.local %{ ; @@ -85,9 +85,9 @@ typedef oop (*prim_t)(oop func, oop self, oop args, oop env); #endif #if PRIMCLOSURE -#define doProtos(_) _(Object) _(GetVar) _(SetVar) _(GetProp) _(SetProp) _(GetArray) _(SetArray) _(Call) _(Invoke) _(Binop) _(Unyop) _(If) _(While) _(Block) _(For) _(ForIn) _(ForFromTo) _(Literal) +#define doProtos(_) _(Object) _(GetVar) _(SetVar) _(GetProp) _(SetProp) _(GetArray) _(SetArray) _(Call) _(Invoke) _(Binop) _(Unyop) _(Let) _(If) _(While) _(Block) _(For) _(ForIn) _(ForFromTo) _(Literal) #else -#define doProtos(_) _(Object) _(GetVar) _(SetVar) _(GetProp) _(SetProp) _(GetArray) _(SetArray) _(Call) _(Invoke) _(Binop) _(Unyop) _(If) _(While) _(Block) _(For) _(ForIn) _(ForFromTo) _(Literal) _(Lambda) _(Closure) +#define doProtos(_) _(Object) _(GetVar) _(SetVar) _(GetProp) _(SetProp) _(GetArray) _(SetArray) _(Call) _(Invoke) _(Binop) _(Unyop) _(Let) _(If) _(While) _(Block) _(For) _(ForIn) _(ForFromTo) _(Literal) _(Lambda) _(Closure) #endif #define declareProto(NAME) oop p##NAME = 0; @@ -114,7 +114,7 @@ doTypes(makeProto); doProperties(declareProp); #undef declareProp -#define doSymbols(_) _(t) _(name) _(expr) _(function) _(arguments) _(object) _(index) _(key) _(value) _(self) _(method) _(parameters) _(body) _(lambda) _(environment) _(operation) _(full) _(condition) _(consequent) _(alternate) _(expression) _(identifier) _(initialise) _(update) _(first) _(last) _(fixed) +#define doSymbols(_) _(t) _(name) _(expr) _(function) _(arguments) _(object) _(index) _(key) _(value) _(self) _(method) _(parameters) _(body) _(lambda) _(environment) _(operation) _(full) _(condition) _(consequent) _(alternate) _(expression) _(identifier) _(initialise) _(update) _(first) _(last) _(fixed) _(keyvals) #define declareSym(NAME) oop sym_##NAME = 0; doSymbols(declareSym); @@ -1564,6 +1564,46 @@ void Unyop_codeOn(oop exp, oop str, oop env) codeOn(str, value, 0); } +oop newLet(void) +{ + oop o = new(pLet); + Object_put(o, sym_keyvals, new(pObject)); + return o; +} + +oop Let_append(oop let, oop key, oop value) +{ + oop keyvals = Object_getLocal(let, sym_keyvals); + Object_push(keyvals, key); + Object_push(keyvals, value); + return let; +} + +oop Let_eval(oop exp, oop env) +{ + oop keyvals = Object_getLocal(exp, sym_keyvals); + oop *indexed = get(keyvals, Object,indexed); + int isize = _get(keyvals, Object,isize); + oop result = nil; + for (int i = 0; i < isize - 1; i += 2) + Object_put(env, indexed[i], (result = eval(indexed[i+1], env))); + return result; +} + +void Let_codeOn(oop exp, oop str, oop env) +{ + oop keyvals = Object_getLocal(exp, sym_keyvals); + oop *indexed = get(keyvals, Object,indexed); + int isize = _get(keyvals, Object,isize); + String_appendAll(str, "let "); + for (int i = 0; i < isize - 1; i += 2) { + if (i) String_appendAll(str, ", "); + codeOn(str, indexed[i], 0); + String_appendAll(str, " = "); + codeOn(str, indexed[i+1], 0); + } +} + oop newIf(oop condition, oop consequent, oop alternate) { oop o = new(pIf); @@ -1871,7 +1911,10 @@ start = - ( s:stmt { yysval = s } | < (!EOL .)* > { fatal("syntax error near: %s", yytext) } ) -stmt = WHILE LPAREN c:expr RPAREN s:stmt { $$ = newWhile(c, s) } +stmt = LET l:mklet k:id ASSIGN v:expr { Let_append(l, k, v) } + ( COMMA k:id ASSIGN v:expr { Let_append(l, k, v) } + )* SEMI { $$ = l } + | WHILE LPAREN c:expr RPAREN s:stmt { $$ = newWhile(c, s) } | IF LPAREN c:expr RPAREN s:stmt ( ELSE t:stmt { $$ = newIf(c, s, t ) } | { $$ = newIf(c, s, nil) } @@ -1887,6 +1930,8 @@ stmt = WHILE LPAREN c:expr RPAREN s:stmt { $$ = newWhile(c, s) } | b:block { $$ = newBlock(b) } | e:expr EOS { $$ = e } +mklet = { $$ = newLet() } + proto = v:var ( DOT j:id !LPAREN { v = newGetProp(v, j) } )* { $$ = v } @@ -2028,6 +2073,7 @@ FOR = "for" !ALNUM - IN = "in" !ALNUM - FROM = "from" !ALNUM - TO = "to" !ALNUM - +LET = "let" !ALNUM - BQUOTE = "`" - COMMAT = "@" -