|
|
@ -1,9 +1,9 @@ |
|
|
|
# minproto.leg -- minimal prototype langauge for semantic experiments |
|
|
|
# |
|
|
|
# last edited: 2024-06-20 13:22:50 by piumarta on m1mbp |
|
|
|
# last edited: 2024-07-05 17:16:16 by piumarta on zora-1034.local |
|
|
|
|
|
|
|
%{ |
|
|
|
; |
|
|
|
; |
|
|
|
//#define YY_DEBUG 1 |
|
|
|
|
|
|
|
#ifndef GC |
|
|
@ -121,9 +121,9 @@ oop printOn(oop buf, oop obj, int indent); |
|
|
|
#endif |
|
|
|
|
|
|
|
#if PRIMCLOSURE |
|
|
|
#define doProtos(_) _(Object) _(RefLocal) _(GetLocal) _(SetLocal) _(RefGlobal) _(GetGlobal) _(SetGlobal) _(RefVar) _(GetVar) _(SetVar) _(RefProp) _(GetProp) _(SetProp) _(RefArray) _(GetArray) _(SetArray) _(GetSlice) _(Call) _(Invoke) _(Super) _(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) _(GetSlice) _(Call) _(Invoke) _(Super) _(Continue) _(Break) _(Return) _(TryCatch) _(TryEnsure)_(Raise)_(Binop) _(Unyop) _(If) _(While) _(Block) _(For) _(ForIn) _(ForFromTo) _(Literal) _(Stream) |
|
|
|
#else |
|
|
|
#define doProtos(_) _(Object) _(RefLocal) _(GetLocal) _(SetLocal) _(RefGlobal) _(GetGlobal) _(SetGlobal) _(RefVar) _(GetVar) _(SetVar) _(RefProp) _(GetProp) _(SetProp) _(RefArray) _(GetArray) _(SetArray) _(GetSlice) _(Call) _(Invoke) _(Super) _(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) _(GetSlice) _(Call) _(Invoke) _(Super) _(Continue) _(Break) _(Return) _(TryCatch) _(TryEnsure) _(Raise) _(Binop) _(Unyop) _(If) _(While) _(Block) _(For) _(ForIn) _(ForFromTo) _(Literal) _(Lambda) _(Closure) _(Stream) |
|
|
|
#endif |
|
|
|
|
|
|
|
#define declareProto(NAME) oop p##NAME = 0; |
|
|
@ -147,7 +147,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) _(p) _(v) _(statement) _(handler) _(kind) _(message) _(operand1) _(operand2) _(profile) _(parent) _(count) _(stamp) _(time) _(start) _(stop) _($$) _(yytext) _(yyleng) |
|
|
|
#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) _(p) _(v) _(statement) _(handler) _(kind) _(message) _(operand1) _(operand2) _(profile) _(parent) _(count) _(stamp) _(time) _(start) _(stop) _($$) _(yytext) _(yyleng) _(env) _(content) _(position) _(limit) _(lastBegin) |
|
|
|
|
|
|
|
#define declareSym(NAME) oop sym_##NAME = 0; |
|
|
|
doSymbols(declareSym); |
|
|
@ -387,10 +387,11 @@ oop String_append(oop str, int c) |
|
|
|
{ |
|
|
|
int length = get(str, String,length); |
|
|
|
char *value = get(str, String,value); |
|
|
|
value = xrealloc(value, length + 1); |
|
|
|
set(str, String,value, value); |
|
|
|
char *copy = xmalloc(length + 1); |
|
|
|
memcpy(copy, value, length); |
|
|
|
set(str, String,value, copy); |
|
|
|
set(str, String,length, length+1); |
|
|
|
value[length] = c; |
|
|
|
copy[length] = c; |
|
|
|
return str; |
|
|
|
} |
|
|
|
|
|
|
@ -399,9 +400,10 @@ oop String_appendAllLen(oop str, char *s, int len) |
|
|
|
if (len < 1) return str; |
|
|
|
int length = get(str, String,length); |
|
|
|
char *value = get(str, String,value); |
|
|
|
value = xrealloc(value, length + len); |
|
|
|
memcpy(value + length, s, len); |
|
|
|
set(str, String,value, value); |
|
|
|
char *copy = xmalloc(length + len); |
|
|
|
memcpy(copy, value, length); |
|
|
|
memcpy(copy + length, s, len); |
|
|
|
set(str, String,value, copy); |
|
|
|
set(str, String,length, length+len); |
|
|
|
return str; |
|
|
|
} |
|
|
@ -422,7 +424,9 @@ oop String_format(oop str, char *fmt, ...) |
|
|
|
int length = get(str, String,length); |
|
|
|
char *value = get(str, String,value); |
|
|
|
for (;;) { |
|
|
|
value = xrealloc(value, length + cap); |
|
|
|
char *orig = value; |
|
|
|
value = xmalloc(length + cap); |
|
|
|
memcpy(value, orig, length); |
|
|
|
va_list ap; |
|
|
|
va_start(ap, fmt); |
|
|
|
len = vsnprintf(value + length, cap, fmt, ap); |
|
|
@ -497,6 +501,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'...'7': --string; c = readCharValue(&string, 8, 3); break; |
|
|
@ -767,7 +773,7 @@ char *storeString(oop obj, int indent); |
|
|
|
|
|
|
|
oop *Object_ref(oop obj, oop key) |
|
|
|
{ |
|
|
|
oop o; |
|
|
|
oop o = nil; |
|
|
|
switch (getType(obj)) { |
|
|
|
case Undefined: o = pUndefined; break; |
|
|
|
case Integer: o = pInteger; break; |
|
|
@ -810,7 +816,7 @@ oop *Object_ref(oop obj, oop key) |
|
|
|
|
|
|
|
oop Object_getOwner(oop obj, oop key, oop *ownerp) |
|
|
|
{ |
|
|
|
oop o; |
|
|
|
oop o = nil; |
|
|
|
switch (getType(obj)) { |
|
|
|
case Undefined: o = pUndefined; break; |
|
|
|
case Integer: o = pInteger; break; |
|
|
@ -853,7 +859,7 @@ oop Object_getOwner(oop obj, oop key, oop *ownerp) |
|
|
|
|
|
|
|
oop Object_get(oop obj, oop key) |
|
|
|
{ |
|
|
|
oop o; |
|
|
|
oop o = nil; |
|
|
|
switch (getType(obj)) { |
|
|
|
case Undefined: o = pUndefined; break; |
|
|
|
case Integer: o = pInteger; break; |
|
|
@ -3336,6 +3342,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); |
|
|
@ -3368,10 +3394,12 @@ void expected(char *what, char *where) |
|
|
|
fatal("syntax error: %s expected near: %s", what, where); |
|
|
|
} |
|
|
|
|
|
|
|
#define global |
|
|
|
|
|
|
|
%} |
|
|
|
|
|
|
|
start = - ( s:stmt { yysval = s } |
|
|
|
| !. { yysval = 0 } |
|
|
|
start = - ( s:stmt { global yysval = s } |
|
|
|
| !. { global yysval = 0 } |
|
|
|
| < (!EOL .)* > { syntaxError(yytext) } |
|
|
|
) |
|
|
|
|
|
|
@ -3457,10 +3485,10 @@ 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: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 } |
|
|
|
|
|
|
|
prefix = PPLUS p:prefix { $$ = newBinop(opPreAdd, lvalue(p), newInteger(1)) } |
|
|
|
| MMINUS p:prefix { $$ = newBinop(opPreSub, lvalue(p), newInteger(1)) } |
|
|
@ -3511,7 +3539,7 @@ params = LPAREN p:mkobj |
|
|
|
) |
|
|
|
)* RPAREN ) { $$ = p } |
|
|
|
|
|
|
|
mkobj = { $$ = new(pObject) } |
|
|
|
mkobj = { $$ = (global new)(pObject) } |
|
|
|
|
|
|
|
primary = nil | number | string | symbol | var | lambda | subexpr | literal # | regex |
|
|
|
|
|
|
@ -3540,8 +3568,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)) } |
|
|
@ -3550,11 +3577,16 @@ unsign = < DIGIT+ '.' DIGIT* EXP? > - { $$ = newFloat(strtod(yytext, 0 |
|
|
|
|
|
|
|
string = '"' < ( !'"' char )* > '"' - { $$ = newStringUnescaped(yytext) } |
|
|
|
|
|
|
|
char = "\\" ( ["'\\abfnrtv] |
|
|
|
| [xX] HIGIT* |
|
|
|
| [0-7][0-7]?[0-7]? |
|
|
|
) |
|
|
|
| . |
|
|
|
char = '\\' [abefnrtv'"\[\]\\] |
|
|
|
| '\\' [0-3][0-7][0-7] |
|
|
|
| '\\' [xX] HIGIT* |
|
|
|
| '\\' [0-7][0-7]? |
|
|
|
| !'\\' . |
|
|
|
# char = "\\" ( ["'\\abfnrtv] |
|
|
|
# | [xX] HIGIT* |
|
|
|
# | [0-7][0-7]?[0-7]? |
|
|
|
# ) |
|
|
|
# | . |
|
|
|
|
|
|
|
symbol = HASH i:id { $$ = i } |
|
|
|
|
|
|
@ -3669,7 +3701,7 @@ SLASH = "/" ![/=] - |
|
|
|
SLASHEQ = "/=" - |
|
|
|
PCENT = "%" ![=] - |
|
|
|
PCENTEQ = "%=" - |
|
|
|
DOT = "." - |
|
|
|
DOT = "." ![.] - |
|
|
|
PLING = "!" ![=] - |
|
|
|
TILDE = "~" - |
|
|
|
|
|
|
@ -3679,6 +3711,7 @@ xexpr = expr | error @{ expected("expression", yytext) } |
|
|
|
|
|
|
|
%% |
|
|
|
; |
|
|
|
#undef global |
|
|
|
|
|
|
|
#if PROFILE |
|
|
|
|
|
|
@ -3903,7 +3936,10 @@ oop eval(oop exp, oop env) |
|
|
|
# if PRIMCLOSURE |
|
|
|
if (Lambda == type) return newClosure(exp, env); |
|
|
|
# endif |
|
|
|
if (Object != type) return exp; |
|
|
|
if (Object != type) { |
|
|
|
if (String == type) return newStringLen(_get(exp, String,value), _get(exp, String,length)); |
|
|
|
return exp; |
|
|
|
} |
|
|
|
if (!opt_O) { |
|
|
|
Object_push(trace, exp); |
|
|
|
if (opt_d && opt_v) { |
|
|
@ -3948,6 +3984,22 @@ oop prim_Object_initialise(oop func, oop self, oop args, oop env) |
|
|
|
return self; |
|
|
|
} |
|
|
|
|
|
|
|
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)); |
|
|
@ -4001,10 +4053,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); |
|
|
|
} |
|
|
@ -4236,6 +4299,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); |
|
|
@ -4291,6 +4395,12 @@ 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)) { |
|
|
|
if (Object_find(args, sym_env) >= 0) { |
|
|
|
env = Object_getLocal(args, sym_env); |
|
|
|
} |
|
|
|
|
|
|
|
for (int i = 0; i < argc; ++i) result = eval(indexed[i], env); |
|
|
|
return result; |
|
|
|
} |
|
|
@ -4300,6 +4410,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); |
|
|
@ -4763,12 +4889,12 @@ oop applyThunkIn(oop func, oop env) |
|
|
|
typedef unsigned char byte; |
|
|
|
|
|
|
|
typedef enum op_t { |
|
|
|
PUSH, DROP, POP, DOT, CLASS, STRING, RULE, CALL, |
|
|
|
PUSH, DROP, POP, DOT, CLASS, STRING, TEST, RULE2, RULE, CALL, |
|
|
|
SUCCEED, FAIL, ACTION, BEGIN, END, UNEND, SET, |
|
|
|
} op_t; |
|
|
|
|
|
|
|
char *op_n[] = { |
|
|
|
"PUSH", "DROP", "POP", "DOT", "CLASS", "STRING", "RULE", "CALL", |
|
|
|
"PUSH", "DROP", "POP", "DOT", "CLASS", "STRING", "TEST", "RULE2", "RULE", "CALL", |
|
|
|
"SUCCEED", "FAIL", "ACTION", "BEGIN", "END", "UNEND", "SET", |
|
|
|
}; |
|
|
|
|
|
|
@ -4779,8 +4905,9 @@ struct vmInsn { |
|
|
|
char *str; |
|
|
|
oop obj; |
|
|
|
vmInsn *code; |
|
|
|
} arg; |
|
|
|
unsigned short op, arglen, ok, ko; |
|
|
|
int len; |
|
|
|
} arg, arg2; |
|
|
|
unsigned short op, ok, ko; |
|
|
|
}; |
|
|
|
|
|
|
|
typedef struct vmState |
|
|
@ -4789,7 +4916,7 @@ typedef struct vmState |
|
|
|
oop variables; |
|
|
|
} vmState; |
|
|
|
|
|
|
|
#define VM_STATE_INITIALISER { nil, nil } |
|
|
|
#define VM_STATE_INITIALISER { nil, new(pObject) } |
|
|
|
|
|
|
|
void vmEnter(vmState *state, oop obj, char *yytext, int yyleng) |
|
|
|
{ |
|
|
@ -4804,7 +4931,7 @@ void vmSet(vmState *state, oop obj, char *yytext, int yyleng) |
|
|
|
|
|
|
|
void vmAction(vmState *state, oop obj, char *yytext, int yyleng) |
|
|
|
{ |
|
|
|
oop text = yyleng ? newStringLen(yytext, yyleng) : nil; |
|
|
|
oop text = yyleng >= 0 ? newStringLen(yytext, yyleng) : nil; |
|
|
|
Object_put(state->variables, sym_yytext, text); |
|
|
|
Object_put(state->variables, sym_yyleng, newInteger(yyleng)); |
|
|
|
applyThunkIn(obj, state->variables); |
|
|
@ -4814,6 +4941,7 @@ void vmLeave(vmState *state, oop obj, char *yytext, int yyleng) |
|
|
|
{ |
|
|
|
state->result = Object_getLocal(state->variables, sym_$$); |
|
|
|
state->variables = _getDelegate(state->variables); |
|
|
|
Object_put(state->variables, sym_$$, state->result); |
|
|
|
} |
|
|
|
|
|
|
|
void vmDisassemble(vmInsn *code, int pc) |
|
|
@ -4824,15 +4952,15 @@ void vmDisassemble(vmInsn *code, int pc) |
|
|
|
case CLASS: |
|
|
|
case STRING: |
|
|
|
printf("%03d %-7s \"%s\" %2d %2d %2d\n", |
|
|
|
pc, op_n[i->op], i->arg.str, i->arglen, i->ok, i->ko); |
|
|
|
pc, op_n[i->op], i->arg.str, i->arg2.len, i->ok, i->ko); |
|
|
|
break; |
|
|
|
case CALL: |
|
|
|
printf("%03d %-7s %p %2d %2d %2d\n", |
|
|
|
pc, op_n[i->op], i->arg.code, i->arglen, i->ok, i->ko); |
|
|
|
pc, op_n[i->op], i->arg.code, i->arg2.len, i->ok, i->ko); |
|
|
|
break; |
|
|
|
default: |
|
|
|
printf("%03d %-7s %s %2d %2d %2d\n", |
|
|
|
pc, op_n[i->op], codeString(i->arg.obj, 0), i->arglen, i->ok, i->ko); |
|
|
|
pc, op_n[i->op], codeString(i->arg.obj, 0), i->arg2.len, i->ok, i->ko); |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
@ -4867,18 +4995,27 @@ vmInsn *vmCompile(oop grammar, oop symbol) |
|
|
|
int cpc = 0; |
|
|
|
while (ppc < plen) { |
|
|
|
int op = integerValue(prog[ppc++], "__match__"); |
|
|
|
oop arg = prog[ppc++]; |
|
|
|
int arglen = integerValue(prog[ppc++], "__match__"); |
|
|
|
oop arg = prog[ppc++]; assert(arg); |
|
|
|
oop arg2 = prog[ppc++]; assert(arg2); |
|
|
|
int ok = integerValue(prog[ppc++], "__match__"); |
|
|
|
int ko = integerValue(prog[ppc++], "__match__"); |
|
|
|
if (ok < 0 || ok >= clen) valueError("__match__", "OK destination out of range", program); |
|
|
|
if (ko < 0 || ko >= clen) valueError("__match__", "KO destination out of range", program); |
|
|
|
code[cpc] = (vmInsn){ .arg.obj = arg, .op = op, .arglen = arglen, .ok = ok, .ko = ko }; |
|
|
|
code[cpc] = (vmInsn){ .arg.obj = arg, .arg2.obj = arg2, .op = op, .ok = ok, .ko = ko }; |
|
|
|
switch (op) { |
|
|
|
case CLASS: |
|
|
|
case STRING: { |
|
|
|
code[cpc].arglen = stringLength(code[cpc].arg.obj, "__match__"); |
|
|
|
code[cpc].arg.str = stringValue (code[cpc].arg.obj, "__match__"); |
|
|
|
code[cpc].arg2.len = stringLength(code[cpc].arg.obj, "__match__"); |
|
|
|
code[cpc].arg.str = stringValue (code[cpc].arg.obj, "__match__"); |
|
|
|
break; |
|
|
|
} |
|
|
|
case TEST: { |
|
|
|
if (!isClosure(code[cpc].arg.obj)) valueError("__match__", "TEST argument must be a closure", program); |
|
|
|
break; |
|
|
|
} |
|
|
|
case RULE2: { |
|
|
|
if (!is(Symbol, code[cpc].arg.obj )) valueError("__match__", "RULE2 argument must be a symbol", program); |
|
|
|
if (!is(Object, code[cpc].arg2.obj)) valueError("__match__", "RULE2 argument2 must be an object", program); |
|
|
|
break; |
|
|
|
} |
|
|
|
case RULE: { |
|
|
@ -4952,6 +5089,7 @@ int vmRun(oop grammar, oop symbol, char *text, int start, int length) |
|
|
|
context.nactions = 0; |
|
|
|
|
|
|
|
vmState state = VM_STATE_INITIALISER; |
|
|
|
state.variables = new(pObject); |
|
|
|
|
|
|
|
# define saveAction(ACT, OBJ, BEG, LEN) { \ |
|
|
|
if (context.nactions >= maxactions) \ |
|
|
@ -4973,7 +5111,6 @@ int vmRun(oop grammar, oop symbol, char *text, int start, int length) |
|
|
|
frame.pc = 0; |
|
|
|
frame.nactions = context.nactions; |
|
|
|
|
|
|
|
|
|
|
|
int textbeg = 0, textend = 0; |
|
|
|
int result = 0; |
|
|
|
|
|
|
@ -4992,6 +5129,8 @@ int vmRun(oop grammar, oop symbol, char *text, int start, int length) |
|
|
|
C##stack[--C##sp]; \ |
|
|
|
}) |
|
|
|
|
|
|
|
saveAction(vmEnter, nil, 0, 0); |
|
|
|
|
|
|
|
for (;;) { |
|
|
|
if (opt_d) vmDisassemble(frame.code, frame.pc); |
|
|
|
vmInsn *i = frame.code + frame.pc++; |
|
|
@ -5021,9 +5160,9 @@ int vmRun(oop grammar, oop symbol, char *text, int start, int length) |
|
|
|
continue; |
|
|
|
} |
|
|
|
case STRING: { |
|
|
|
if (context.position + i->arglen <= length) { |
|
|
|
if (0 == memcmp(text + context.position, i->arg.str, i->arglen)) { |
|
|
|
context.position += i->arglen; |
|
|
|
if (context.position + i->arg2.len <= length) { |
|
|
|
if (0 == memcmp(text + context.position, i->arg.str, i->arg2.len)) { |
|
|
|
context.position += i->arg2.len; |
|
|
|
frame.pc = i->ok; |
|
|
|
continue; |
|
|
|
} |
|
|
@ -5031,6 +5170,16 @@ int vmRun(oop grammar, oop symbol, char *text, int start, int length) |
|
|
|
frame.pc = i->ko; |
|
|
|
continue; |
|
|
|
} |
|
|
|
case TEST: { |
|
|
|
oop result = apply(i->arg.obj, nil, new(pObject), nil, nil); |
|
|
|
frame.pc = (nil == result) ? i->ko : i->ok; |
|
|
|
continue; |
|
|
|
} |
|
|
|
case RULE2: { |
|
|
|
i->op = CALL; |
|
|
|
i->arg.code = vmCacheGet(i->arg2.obj, i->arg.obj); |
|
|
|
goto doCall; |
|
|
|
} |
|
|
|
case RULE: { |
|
|
|
// frame.pc--; // save pc of call insn |
|
|
|
// push(r, frame); |
|
|
@ -5073,11 +5222,15 @@ int vmRun(oop grammar, oop symbol, char *text, int start, int length) |
|
|
|
} |
|
|
|
case FAIL: { |
|
|
|
if (rsp) { |
|
|
|
context.nactions = frame.nactions - 1; // remove all actions added by this rule |
|
|
|
frame = pop(r); |
|
|
|
i = frame.code + frame.pc; |
|
|
|
frame.pc = i->ko; |
|
|
|
continue; |
|
|
|
} |
|
|
|
else { |
|
|
|
context.nactions = 0; |
|
|
|
} |
|
|
|
result = -1; |
|
|
|
break; |
|
|
|
} |
|
|
@ -5115,8 +5268,6 @@ int vmRun(oop grammar, oop symbol, char *text, int start, int length) |
|
|
|
break; |
|
|
|
} |
|
|
|
|
|
|
|
saveAction(vmLeave, nil, 0, 0); |
|
|
|
|
|
|
|
#undef pop |
|
|
|
#undef drop |
|
|
|
#undef push |
|
|
@ -5153,6 +5304,20 @@ oop prim_match(oop func, oop self, oop args, oop env) |
|
|
|
|
|
|
|
#endif // PEGVM |
|
|
|
|
|
|
|
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; |
|
|
@ -5278,6 +5443,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 |
|
|
|
|
|
|
|
#undef stringify |
|
|
|
|
|
|
|
#define declareOp(NAME, OP) _set(intern(#NAME), Symbol,value, newInteger(NAME)); |
|
|
|
doUnyops(declareOp) |
|
|
|
#undef declareOp |
|
|
|
|
|
|
|
#if TYPECODES |
|
|
|
|
|
|
|
# define defineEvaluator(NAME) \ |
|
|
@ -5323,6 +5500,12 @@ int main(int argc, char **argv) |
|
|
|
prim(defined , prim_defined); |
|
|
|
prim(__extern__ , prim_extern); |
|
|
|
prim(__match__ , prim_match); |
|
|
|
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 |
|
|
|
|
|
|
@ -5365,6 +5548,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 |
|
|
|
|
|
|
|