|
|
@ -1,6 +1,6 @@ |
|
|
|
# minproto.leg -- minimal prototype langauge for semantic experiments |
|
|
|
# |
|
|
|
# last edited: 2024-05-29 10:02:58 by piumarta on zora |
|
|
|
# last edited: 2024-05-29 11:05:04 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) _(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) _(Range) _(Stream) |
|
|
|
#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) _(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) _(Range) _(Stream) |
|
|
|
#endif |
|
|
|
|
|
|
|
#define declareProto(NAME) oop p##NAME = 0; |
|
|
@ -134,7 +134,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) _(keyvals) _(__namespaces__) _(O) _(d) _(v) _(statement) _(handler) _(kind) _(message) _(operand1) _(operand2) |
|
|
|
#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) _(__namespaces__) _(O) _(d) _(v) _(statement) _(handler) _(kind) _(message) _(operand1) _(operand2) _(start) _(end) _(env) _(content) _(position) _(limit) _(lastBegin) |
|
|
|
|
|
|
|
#define declareSym(NAME) oop sym_##NAME = 0; |
|
|
|
doSymbols(declareSym); |
|
|
@ -478,6 +478,8 @@ oop newStringUnescaped(char *string) |
|
|
|
case 'r' : c = '\r'; break; |
|
|
|
case 't' : c = '\t'; break; |
|
|
|
case 'v' : c = '\v'; break; |
|
|
|
case '[' : c = '[' ; break; |
|
|
|
case ']' : c = ']' ; break; |
|
|
|
case 'X' : |
|
|
|
case 'x' : c = readCharValue(&string, 16, -1); break; |
|
|
|
case '0' : c = readCharValue(&string, 8, 3); break; |
|
|
@ -1813,7 +1815,18 @@ oop GetArray_eval(oop exp, oop env) |
|
|
|
default: typeError("[]", "non-indexable object", obj); |
|
|
|
} |
|
|
|
} |
|
|
|
if (!is(Object, obj)) typeError("[]", "non-indexable object", obj); |
|
|
|
if (getType(ind) == Object && Object_get(ind, prop_name) == Object_get(pRange, prop_name)) { |
|
|
|
switch (getType(obj)) { |
|
|
|
case String: { |
|
|
|
int start = integerValue(eval(Object_get(ind, sym_start), env), "[..]"); |
|
|
|
int end = integerValue(eval(Object_get(ind, sym_end ), env), "[..]"); |
|
|
|
oop slice = newStringLen(String_aref(obj, start), end - start); |
|
|
|
return slice; |
|
|
|
} |
|
|
|
default: fatal("[]: %s is not range - indexable", storeString(obj, 0)); |
|
|
|
} |
|
|
|
} |
|
|
|
if (!is(Object, obj)) fatal("[]: %s is not an object", storeString(obj, 0)); |
|
|
|
return Object_getLocal(obj, ind); |
|
|
|
} |
|
|
|
|
|
|
@ -1862,6 +1875,25 @@ void SetArray_codeOn(oop exp, oop str, oop env) |
|
|
|
codeOn(str, Object_get(exp, sym_value), 0); |
|
|
|
} |
|
|
|
|
|
|
|
oop newRange(oop start, oop end) { |
|
|
|
oop o = new(pRange); |
|
|
|
Object_put(o, sym_start, start); |
|
|
|
Object_put(o, sym_end, end); |
|
|
|
return o; |
|
|
|
} |
|
|
|
|
|
|
|
oop Range_eval(oop exp, oop env) |
|
|
|
{ |
|
|
|
return exp; |
|
|
|
} |
|
|
|
|
|
|
|
void Range_codeOn(oop exp, oop str, oop env) |
|
|
|
{ |
|
|
|
codeOn(str, Object_get(exp, sym_start), 0); |
|
|
|
String_appendAll(str, ".."); |
|
|
|
codeOn(str, Object_get(exp, sym_end), 0); |
|
|
|
} |
|
|
|
|
|
|
|
oop newCall(oop function, oop arguments) |
|
|
|
{ |
|
|
|
oop o = new(pCall); |
|
|
@ -3070,6 +3102,26 @@ void Literal_codeOn(oop exp, oop str, oop env) |
|
|
|
# endif |
|
|
|
} |
|
|
|
|
|
|
|
oop newStream(oop content) |
|
|
|
{ |
|
|
|
oop o = new(pStream); |
|
|
|
Object_put(o, sym_content , content); |
|
|
|
Object_put(o, sym_position , newInteger(0)); |
|
|
|
Object_put(o, sym_limit , newInteger(_get(content, String, length))); |
|
|
|
Object_put(o, sym_lastBegin, newInteger(0)); |
|
|
|
return o; |
|
|
|
} |
|
|
|
|
|
|
|
oop Stream_eval(oop exp, oop env) |
|
|
|
{ |
|
|
|
return exp; |
|
|
|
} |
|
|
|
|
|
|
|
void Stream_codeOn(oop exp, oop str, oop env) |
|
|
|
{ |
|
|
|
Object_codeOn(exp, str, env); |
|
|
|
} |
|
|
|
|
|
|
|
oop lvalue(oop rval) |
|
|
|
{ |
|
|
|
if (!is(Object,rval)) valueError("=", "non-assignable value", rval); |
|
|
@ -3187,10 +3239,13 @@ sum = l:prod ( PLUS r:prod { l = newBinop(opAdd, l, r) } |
|
|
|
| MINUS r:prod { l = newBinop(opSub, l, r) } |
|
|
|
)* { $$ = l } |
|
|
|
|
|
|
|
prod = l:prefix ( STAR r:prefix { l = newBinop(opMul, l, r) } |
|
|
|
| SLASH r:prefix { l = newBinop(opDiv, l, r) } |
|
|
|
| PCENT r:prefix { l = newBinop(opMod, l, r) } |
|
|
|
)* { $$ = l } |
|
|
|
prod = l:range ( STAR r:range { l = newBinop(opMul, l, r) } |
|
|
|
| SLASH r:range { l = newBinop(opDiv, l, r) } |
|
|
|
| PCENT r:range { l = newBinop(opMod, l, r) } |
|
|
|
) * { $$ = l } |
|
|
|
|
|
|
|
range = i1:prefix ( DOTDOT i2:prefix { i1 = newRange(i1, i2) } |
|
|
|
) ? { $$ = i1 } |
|
|
|
|
|
|
|
prefix = PPLUS p:prefix { $$ = newBinop(opPreAdd, lvalue(p), newInteger(1)) } |
|
|
|
| MMINUS p:prefix { $$ = newBinop(opPreSub, lvalue(p), newInteger(1)) } |
|
|
@ -3260,8 +3315,7 @@ number = "-" n:unsign { $$ = neg(n) } |
|
|
|
| "+" n:number { $$ = n } |
|
|
|
| n:unsign { $$ = n } |
|
|
|
|
|
|
|
unsign = < DIGIT+ '.' DIGIT* EXP? > - { $$ = newFloat(strtod(yytext, 0)) } |
|
|
|
| < DIGIT* '.' DIGIT+ EXP? > - { $$ = newFloat(strtod(yytext, 0)) } |
|
|
|
unsign = < DIGIT* '.' DIGIT+ EXP? > - { $$ = newFloat(strtod(yytext, 0)) } |
|
|
|
| "0" [bB] < BIGIT+ > - { $$ = newInteger(strtol(yytext, 0, 2)) } |
|
|
|
| "0" [xX] < HIGIT+ > - { $$ = newInteger(strtol(yytext, 0, 16)) } |
|
|
|
| "0" < OIGIT* > - { $$ = newInteger(strtol(yytext, 0, 8)) } |
|
|
@ -3359,7 +3413,8 @@ SLASH = "/" ![/=] - |
|
|
|
SLASHEQ = "/=" - |
|
|
|
PCENT = "%" ![=] - |
|
|
|
PCENTEQ = "%=" - |
|
|
|
DOT = "." - |
|
|
|
DOT = "." ![.] - |
|
|
|
DOTDOT = ".." - |
|
|
|
PLING = "!" ![=] - |
|
|
|
TILDE = "~" - |
|
|
|
|
|
|
@ -3546,13 +3601,28 @@ oop prim_new(oop func, oop self, oop args, oop env) |
|
|
|
return args; |
|
|
|
} |
|
|
|
|
|
|
|
oop prim_newBinop(oop func, oop self, oop args, oop env) |
|
|
|
{ assert(is(Object, args)); |
|
|
|
int argc = _get(args, Object,isize); |
|
|
|
if (argc != 3) fatal("newBinop: Expected 3 arguments, got %d\n", argc); |
|
|
|
oop *indexed = _get(args, Object,indexed); |
|
|
|
return newBinop(integerValue(indexed[0], "prim_newBinop"), indexed[1], indexed[2]); |
|
|
|
} |
|
|
|
|
|
|
|
oop prim_newApply(oop func, oop self, oop args, oop env) |
|
|
|
{ assert(is(Object, args)); |
|
|
|
int argc = _get(args, Object,isize); |
|
|
|
if (argc != 2) fatal("newApply: Expected 2 arguments, got %d\n", argc); |
|
|
|
oop *indexed = _get(args, Object,indexed); |
|
|
|
return newApply(indexed[0], indexed[1]); |
|
|
|
} |
|
|
|
|
|
|
|
oop prim_Object_push(oop func, oop self, oop args, oop env) |
|
|
|
{ assert(is(Object, args)); |
|
|
|
int argc = _get(args, Object,isize); assert(is(Object, self)); |
|
|
|
oop *indexed = _get(args, Object,indexed); |
|
|
|
oop result = nil; |
|
|
|
for (int i = 0; i < argc; ++i) result = Object_push(self, indexed[i]); |
|
|
|
return result; |
|
|
|
for (int i = 0; i < argc; ++i) Object_push(self, indexed[i]); |
|
|
|
return self; |
|
|
|
} |
|
|
|
|
|
|
|
oop prim_Object_pop(oop func, oop self, oop args, oop env) |
|
|
@ -3597,10 +3667,21 @@ oop prim_String_pop(oop func, oop self, oop args, oop env) |
|
|
|
} |
|
|
|
|
|
|
|
oop prim_String_asInteger(oop func, oop self, oop args, oop env) |
|
|
|
{ assert(is(String, self)); |
|
|
|
{ assert(is(Object, args)); |
|
|
|
int argc = _get(args, Object,isize); assert(is(String, self)); |
|
|
|
if (argc > 1) fatal("String.asInteger: expected either 0 or 1 arguments, got %d\n", argc); |
|
|
|
|
|
|
|
char *str = String_content(self); // ensure nul terminator |
|
|
|
char *end = 0; |
|
|
|
long value = strtol(str, &end, 0); |
|
|
|
long value; |
|
|
|
|
|
|
|
if (argc == 1) { |
|
|
|
oop base = _get(args, Object,indexed)[0]; |
|
|
|
value = strtol(str, &end, integerValue(base, "String.asInteger")); |
|
|
|
} else { |
|
|
|
value = strtol(str, &end, 0); |
|
|
|
} |
|
|
|
|
|
|
|
if (*end) return nil; |
|
|
|
return newInteger(value); |
|
|
|
} |
|
|
@ -3703,6 +3784,47 @@ oop prim_Symbol_asString(oop func, oop self, oop args, oop env) |
|
|
|
return newString(_get(self, Symbol,name)); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
oop prim_newStream(oop func, oop self, oop args, oop env) |
|
|
|
{ assert(is(Object, args)); |
|
|
|
int argc = _get(args, Object,isize); |
|
|
|
if (argc != 1) fatal("newStream: Expected 1 argument, got %d\n", argc); |
|
|
|
oop arg = _get(args, Object, indexed)[0]; |
|
|
|
if (!is(String, arg)) fatal("newStream: expected an argument of type String, got type %s instead\n", getType(arg)); |
|
|
|
return newStream(arg); |
|
|
|
} |
|
|
|
|
|
|
|
oop prim_Stream_atEnd(oop func, oop self, oop args, oop env) |
|
|
|
{ |
|
|
|
return newBoolean(_integerValue(Object_get(self, sym_position)) >= _integerValue(Object_get(self, sym_limit))); |
|
|
|
} |
|
|
|
|
|
|
|
oop prim_Stream_inc(oop func, oop self, oop args, oop env) |
|
|
|
{ |
|
|
|
if (_integerValue(Object_get(self, sym_position)) < _integerValue(Object_get(self, sym_limit))) { |
|
|
|
// There has to be a better way of just adding 1 |
|
|
|
Object_put(self, sym_position, newInteger(_integerValue(Object_get(self, sym_position)) + 1)); |
|
|
|
} |
|
|
|
return Object_get(self, sym_position); |
|
|
|
} |
|
|
|
|
|
|
|
oop prim_Stream_setLastBegin(oop func, oop self, oop args, oop env) |
|
|
|
{ |
|
|
|
return Object_put(self, sym_lastBegin, newInteger(_integerValue(Object_get(self, sym_position)))); |
|
|
|
} |
|
|
|
|
|
|
|
oop prim_Stream_match(oop func, oop self, oop args, oop env) |
|
|
|
{ assert(is(Object, args)); |
|
|
|
int argc = _get(args, Object,isize); |
|
|
|
if (argc != 1) fatal("Stream.match: Expected 1 argument, got %d\n", argc); |
|
|
|
oop arg = _get(args, Object, indexed)[0]; assert(is(String, arg)); |
|
|
|
return newBoolean(strncmp( |
|
|
|
String_content(Object_get(self, sym_content)) + _integerValue(Object_get(self, sym_position)), |
|
|
|
String_content(arg), |
|
|
|
strlen(String_content(arg)) |
|
|
|
) == 0); |
|
|
|
} |
|
|
|
|
|
|
|
oop prim_length(oop func, oop self, oop args, oop env) |
|
|
|
{ assert(is(Object, args)); |
|
|
|
if (!is(Object, self)) valueError("length", "not an object", self); |
|
|
@ -3758,6 +3880,11 @@ oop prim_eval(oop func, oop self, oop args, oop env) |
|
|
|
int argc = _get(args, Object,isize); |
|
|
|
oop *indexed = _get(args, Object,indexed); |
|
|
|
oop result = nil; |
|
|
|
|
|
|
|
if (nil != Object_getLocal(args, sym_env)) { |
|
|
|
env = Object_getLocal(args, sym_env); |
|
|
|
} |
|
|
|
|
|
|
|
for (int i = 0; i < argc; ++i) result = eval(indexed[i], env); |
|
|
|
return result; |
|
|
|
} |
|
|
@ -3767,6 +3894,22 @@ oop prim___eval__(oop func, oop self, oop args, oop env) |
|
|
|
return self; |
|
|
|
} |
|
|
|
|
|
|
|
oop prim_intern(oop func, oop self, oop args, oop env) |
|
|
|
{ |
|
|
|
int argc = _get(args, Object,isize); |
|
|
|
oop *indexed = _get(args, Object,indexed); |
|
|
|
oop result = nil; |
|
|
|
|
|
|
|
if (argc != 1) { |
|
|
|
fatal("intern: invalid number of arguments"); |
|
|
|
} |
|
|
|
if (getType(indexed[0]) != String) { |
|
|
|
fatal("intern: argument is not of type String, got %s instead", getTypeName(indexed[0])); |
|
|
|
} |
|
|
|
|
|
|
|
return intern(String_content(indexed[0])); |
|
|
|
} |
|
|
|
|
|
|
|
oop prim_print(oop func, oop self, oop args, oop env) |
|
|
|
{ |
|
|
|
int argc = _get(args, Object,isize); |
|
|
@ -3965,6 +4108,20 @@ oop prim_Symbol_allInstances(oop func, oop self, oop args, oop env) |
|
|
|
return result; |
|
|
|
} |
|
|
|
|
|
|
|
oop prim_lvalue(oop func, oop self, oop args, oop env) |
|
|
|
{ assert(is(Object, args)); |
|
|
|
int argc = _get(args, Object,isize); |
|
|
|
if (argc != 1) fatal("lvalue: one argument expected\n"); |
|
|
|
return lvalue(_get(args, Object,indexed)[0]); |
|
|
|
} |
|
|
|
|
|
|
|
oop prim_assign(oop func, oop self, oop args, oop env) |
|
|
|
{ assert(is(Object, args)); |
|
|
|
int argc = _get(args, Object,isize); |
|
|
|
if (argc != 2) fatal("assign: 2 arguments expected\n"); |
|
|
|
return assign(_get(args, Object,indexed)[0], _get(args, Object,indexed)[1]); |
|
|
|
} |
|
|
|
|
|
|
|
oop replFile(FILE *in) |
|
|
|
{ |
|
|
|
int oldline = lineno; |
|
|
@ -4085,6 +4242,18 @@ int main(int argc, char **argv) |
|
|
|
|
|
|
|
Object_put(pObject, prop_eval, newPrimitive(prim___eval__, newString("Object.__eval__"))); // inherited by all objects |
|
|
|
|
|
|
|
#define stringify(x) #x |
|
|
|
|
|
|
|
#define declareOp(NAME, OP) _set(intern(stringify(__op##NAME)), Symbol,value, newInteger(op##NAME)); |
|
|
|
doBinops(declareOp) |
|
|
|
#undef declareOp |
|
|
|
|
|
|
|
#define declareOp(NAME, OP) _set(intern(stringify(__##NAME)), Symbol,value, newInteger(NAME)); |
|
|
|
doUnyops(declareOp) |
|
|
|
#undef declareOp |
|
|
|
|
|
|
|
#undef stringify |
|
|
|
|
|
|
|
#if TYPECODES |
|
|
|
|
|
|
|
# define defineEvaluator(NAME) \ |
|
|
@ -4128,6 +4297,12 @@ int main(int argc, char **argv) |
|
|
|
prim(exit , prim_exit); |
|
|
|
prim(error , prim_error); |
|
|
|
prim(defined , prim_defined); |
|
|
|
prim(intern , prim_intern); |
|
|
|
prim(newBinop , prim_newBinop); |
|
|
|
prim(newApply , prim_newApply); |
|
|
|
prim(lvalue , prim_lvalue); |
|
|
|
prim(assign , prim_assign); |
|
|
|
prim(newStream , prim_newStream); |
|
|
|
|
|
|
|
# undef prim |
|
|
|
|
|
|
@ -4160,6 +4335,10 @@ int main(int argc, char **argv) |
|
|
|
method(Symbol,define, prim_Symbol_define ); |
|
|
|
method(Symbol,value, prim_Symbol_value ); |
|
|
|
method(Symbol,allInstances, prim_Symbol_allInstances); |
|
|
|
method(Stream,atEnd, prim_Stream_atEnd ); |
|
|
|
method(Stream,inc, prim_Stream_inc ); |
|
|
|
method(Stream,setLastBegin, prim_Stream_setLastBegin); |
|
|
|
method(Stream,match, prim_Stream_match ); |
|
|
|
|
|
|
|
# undef method |
|
|
|
|
|
|
|