diff --git a/minproto.leg b/minproto.leg index 3f4ac07..d4baf39 100644 --- a/minproto.leg +++ b/minproto.leg @@ -1,6 +1,6 @@ # minproto.leg -- minimal prototype langauge for semantic experiments # -# last edited: 2024-05-29 14:20:52 by piumarta on zora +# last edited: 2024-05-30 14:46:11 by piumarta on zora %{ ; @@ -108,9 +108,9 @@ oop printOn(oop buf, oop obj, int indent); #endif #if PRIMCLOSURE -#define doProtos(_) _(Object) _(RefSym) _(GetSym) _(SetSym) _(RefVar) _(GetVar) _(SetVar) _(RefProp) _(GetProp) _(SetProp) _(RefArray) _(GetArray) _(SetArray) _(Call) _(Invoke) _(Continue) _(Break) _(Return) _(TryCatch) _(TryEnsure)_(Raise)_(Binop) _(Unyop) _(If) _(While) _(Block) _(For) _(ForIn) _(ForFromTo) _(Literal) +#define doProtos(_) _(Object) _(RefLocal) _(GetLocal) _(SetLocal) _(RefGlobal) _(GetGlobal) _(SetGlobal) _(RefVar) _(GetVar) _(SetVar) _(RefProp) _(GetProp) _(SetProp) _(RefArray) _(GetArray) _(SetArray) _(Call) _(Invoke) _(Continue) _(Break) _(Return) _(TryCatch) _(TryEnsure)_(Raise)_(Binop) _(Unyop) _(If) _(While) _(Block) _(For) _(ForIn) _(ForFromTo) _(Literal) #else -#define doProtos(_) _(Object) _(RefSym) _(GetSym) _(SetSym) _(RefVar) _(GetVar) _(SetVar) _(RefProp) _(GetProp) _(SetProp) _(RefArray) _(GetArray) _(SetArray) _(Call) _(Invoke) _(Continue) _(Break) _(Return) _(TryCatch) _(TryEnsure) _(Raise) _(Binop) _(Unyop) _(If) _(While) _(Block) _(For) _(ForIn) _(ForFromTo) _(Literal) _(Lambda) _(Closure) +#define doProtos(_) _(Object) _(RefLocal) _(GetLocal) _(SetLocal) _(RefGlobal) _(GetGlobal) _(SetGlobal) _(RefVar) _(GetVar) _(SetVar) _(RefProp) _(GetProp) _(SetProp) _(RefArray) _(GetArray) _(SetArray) _(Call) _(Invoke) _(Continue) _(Break) _(Return) _(TryCatch) _(TryEnsure) _(Raise) _(Binop) _(Unyop) _(If) _(While) _(Block) _(For) _(ForIn) _(ForFromTo) _(Literal) _(Lambda) _(Closure) #endif #define declareProto(NAME) oop p##NAME = 0; @@ -824,9 +824,14 @@ oop setvar(oop obj, oop key, oop val) if (ind >= 0) return _get(env, Object,properties)[ind].val = val; // set it env = _getDelegate(env); } - return (nil == obj) // are we at the top level? - ? _get(key, Symbol,value) = val // set a global variable - : Object_put(obj, key, val); // create a new local variable + if (nil != obj) return Object_put(obj, key, val); // create a new local variable + int numspaces = _get(namespaces, Object,isize); + if (numspaces) { + oop *nss = _get(namespaces, Object,indexed); + oop ns = nss[numspaces - 1]; + if (is(Object, ns)) return Object_put(ns, key, val); // define a namespace variable + } + return _get(key, Symbol,value) = val; // set a global variable } oop Object_put(oop obj, oop key, oop val) @@ -1536,33 +1541,101 @@ extern inline oop mkptr(void *address) return o; } -oop newRefSym(oop name) +oop newRefLocal(oop name) +{ + oop o = new(pRefLocal); + Object_put(o, sym_name, name); + return o; +} + +oop RefLocal_eval(oop exp, oop env) +{ + if (!is(Object, env)) valueError("local", "not in a local scope", exp); + oop sym = Object_get(exp, sym_name); + oop *ref = Object_refLocal(env, sym); + if (!ref) undefinedError(sym); + return mkptr(ref); +} + +void RefLocal_codeOn(oop exp, oop str, oop env) +{ + String_appendAll(str, "local "); + printOn(str, Object_get(exp, sym_name), 0); +} + +oop newGetLocal(oop name) +{ + oop o = new(pGetLocal); + Object_put(o, sym_name, name); + return o; +} + +oop GetLocal_eval(oop exp, oop env) +{ + if (!is(Object, env)) valueError("local", "not in a local scope", exp); + oop sym = Object_get(exp, sym_name); + oop *ref = Object_refLocal(env, sym); + if (!ref) undefinedError(sym); + return *ref; +} + +void GetLocal_codeOn(oop exp, oop str, oop env) +{ + String_appendAll(str, "local "); + printOn(str, Object_get(exp, sym_name), 0); +} + +oop newSetLocal(oop name, oop value) +{ + oop o = new(pSetLocal); + Object_put(o, sym_name, name); + Object_put(o, sym_value, value); + return o; +} + +oop SetLocal_eval(oop exp, oop env) +{ + if (!is(Object, env)) valueError("local", "not in a local scope", exp); + oop sym = Object_get(exp, sym_name ); + oop val = eval(Object_get(exp, sym_value), env); + return Object_put(env, sym, val); +} + +void SetLocal_codeOn(oop exp, oop str, oop env) +{ + String_appendAll(str, "local "); + printOn(str, Object_get(exp, sym_name), 0); + String_appendAll(str, " = "); + codeOn(str, Object_get(exp, sym_value), 0); +} + +oop newRefGlobal(oop name) { - oop o = new(pRefSym); + oop o = new(pRefGlobal); Object_put(o, sym_name, name); return o; } -oop RefSym_eval(oop exp, oop env) +oop RefGlobal_eval(oop exp, oop env) { oop sym = Object_get(exp, sym_name); return mkptr(&_get(sym, Symbol,value)); } -void RefSym_codeOn(oop exp, oop str, oop env) +void RefGlobal_codeOn(oop exp, oop str, oop env) { String_appendAll(str, "global "); printOn(str, Object_get(exp, sym_name), 0); } -oop newGetSym(oop name) +oop newGetGlobal(oop name) { - oop o = new(pGetSym); + oop o = new(pGetGlobal); Object_put(o, sym_name, name); return o; } -oop GetSym_eval(oop exp, oop env) +oop GetGlobal_eval(oop exp, oop env) { oop sym = Object_get(exp, sym_name); oop val = _get(sym, Symbol,value); @@ -1570,28 +1643,28 @@ oop GetSym_eval(oop exp, oop env) return val; } -void GetSym_codeOn(oop exp, oop str, oop env) +void GetGlobal_codeOn(oop exp, oop str, oop env) { String_appendAll(str, "global "); printOn(str, Object_get(exp, sym_name), 0); } -oop newSetSym(oop name, oop value) +oop newSetGlobal(oop name, oop value) { - oop o = new(pSetSym); + oop o = new(pSetGlobal); Object_put(o, sym_name, name); Object_put(o, sym_value, value); return o; } -oop SetSym_eval(oop exp, oop env) +oop SetGlobal_eval(oop exp, oop env) { oop sym = Object_get(exp, sym_name ) ; oop val = eval(Object_get(exp, sym_value), env); return _set(sym, Symbol,value, val); } -void SetSym_codeOn(oop exp, oop str, oop env) +void SetGlobal_codeOn(oop exp, oop str, oop env) { String_appendAll(str, "global "); printOn(str, Object_get(exp, sym_name), 0); @@ -3067,10 +3140,11 @@ oop lvalue(oop rval) { if (!is(Object,rval)) valueError("=", "non-assignable value", rval); oop kind = _getDelegate(rval); - if (kind == pGetVar ) kind = pRefVar; - else if (kind == pGetProp ) kind = pRefProp; - else if (kind == pGetArray) kind = pRefArray; - else if (kind == pGetSym ) kind = pRefSym; + if (kind == pGetVar ) kind = pRefVar; + else if (kind == pGetProp ) kind = pRefProp; + else if (kind == pGetArray ) kind = pRefArray; + else if (kind == pGetLocal ) kind = pRefLocal; + else if (kind == pGetGlobal) kind = pRefGlobal; else valueError("=", "non-assignable value", rval); _setDelegate(rval, kind); return rval; @@ -3083,7 +3157,6 @@ oop assign(oop rval, oop value) if (kind == pGetVar ) kind = pSetVar; else if (kind == pGetProp ) kind = pSetProp; else if (kind == pGetArray) kind = pSetArray; - else if (kind == pGetSym ) kind = pSetSym; else valueError("=", "non-assignable value", rval); _setDelegate(rval, kind); Object_put(rval, sym_value, value); @@ -3123,7 +3196,9 @@ stmt = WHILE LPAREN c:expr RPAREN s:stmt { $$ = newWhile(c, s) } | ENSURE e:stmt { $$ = newTryEnsure(t, e) } ) | RAISE e:expr EOS { $$ = newRaise(e) } - | i:id p:params b:block { $$ = newSetVar(i, newLambda(p, b)) } + | LOCAL i:id p:params b:block { $$ = newSetLocal (i, newLambda(p, b)) } + | GLOBAL i:id p:params b:block { $$ = newSetGlobal(i, newLambda(p, b)) } + | i:id p:params b:block { $$ = newSetVar (i, newLambda(p, b)) } | v:proto DOT i:id p:params b:block { $$ = newSetProp(v, i, newLambda(p, b)) } | b:block { $$ = newBlock(b) } | e:expr EOS { $$ = e } @@ -3133,7 +3208,9 @@ proto = v:var ( DOT j:id !LPAREN { v = newGetProp(v, j) } EOS = SEMI+ | &RBRACE | &ELSE | &CATCH -expr = i:id ASSIGN e:expr { $$ = newSetVar(i, e) } +expr = LOCAL i:id ASSIGN e:expr { $$ = newSetLocal (i, e) } + | GLOBAL i:id ASSIGN e:expr { $$ = newSetGlobal(i, e) } + | i:id ASSIGN e:expr { $$ = newSetVar (i, e) } | l:logor ( ASSIGN r:expr { l = assign(l, r) } | PLUSEQ r:expr { l = newBinop(opPreAdd, lvalue(l), r) } | MINUSEQ r:expr { l = newBinop(opPreSub, lvalue(l), r) } @@ -3271,8 +3348,9 @@ char = "\\" ( ["'\\abfnrtv] symbol = HASH i:id { $$ = i } -var = GLOBAL i:id { $$ = newGetSym(i) } - | i:id { $$ = newGetVar(i) } +var = LOCAL i:id { $$ = newGetLocal (i) } + | GLOBAL i:id { $$ = newGetGlobal(i) } + | i:id { $$ = newGetVar (i) } id = < LETTER ALNUM* > - { $$ = intern(yytext) } @@ -3308,6 +3386,7 @@ CATCH = "catch" !ALNUM - ENSURE = "ensure" !ALNUM - RAISE = "raise" !ALNUM - GLOBAL = "global" !ALNUM - +LOCAL = "local" !ALNUM - BQUOTE = "`" - COMMAT = "@" -