Преглед изворни кода

Fix relations to compare more than just integers, fix semicolons to end

an expression, add for in structure, refactor apply (merge with invoke),
transform millis to microseconds, mix boxed/unboxed integers
pull/16/head
mtardy пре 4 година
родитељ
комит
f42be7d411
5 измењених фајлова са 355 додато и 443 уклоњено
  1. +67
    -90
      object.c
  2. +224
    -340
      parse.leg
  3. +5
    -0
      test-error.txt
  4. +30
    -0
      test-namespace.txt
  5. +29
    -13
      test-object.txt

+ 67
- 90
object.c Прегледај датотеку

@ -5,21 +5,33 @@
#include <assert.h> #include <assert.h>
#define USE_TAG 1 #define USE_TAG 1
#define USE_GC 1 #define USE_GC 1
#if (USE_GC) #if (USE_GC)
# include <gc.h> # include <gc.h>
#endif #endif
typedef long long int_t;
#define FMT_I "%lli"
void *memcheck(void *ptr)
{
if (NULL == ptr) {
fprintf(stderr, "Error: out of memory\n");
exit(EX_OSERR); // this is as close as we have for 'resource unavailable'
}
return ptr;
}
void *xmalloc(size_t n) void *xmalloc(size_t n)
{ {
#if (USE_GC) #if (USE_GC)
void *mem= GC_malloc(n); void *mem= GC_malloc(n);
assert(mem);
#else #else
void *mem= calloc(1, n);
void *mem= memcheck(calloc(1, n));
#endif #endif
assert(mem);
return mem; return mem;
} }
@ -27,10 +39,10 @@ void *xrealloc(void *p, size_t n)
{ {
#if (USE_GC) #if (USE_GC)
void *mem= GC_realloc(p, n); void *mem= GC_realloc(p, n);
assert(mem);
#else #else
void *mem= realloc(p, n);
void *mem= memcheck(realloc(p, n));
#endif #endif
assert(mem);
return mem; return mem;
} }
@ -39,11 +51,11 @@ char *xstrdup(char *s)
#if (USE_GC) #if (USE_GC)
size_t len= strlen(s); size_t len= strlen(s);
char *mem= GC_malloc_atomic(len + 1); char *mem= GC_malloc_atomic(len + 1);
assert(mem);
memcpy(mem, s, len + 1); memcpy(mem, s, len + 1);
#else #else
char *mem= strdup(s);
char *mem= memcheck(strdup(s));
#endif #endif
assert(mem);
return mem; return mem;
} }
@ -69,7 +81,7 @@ struct Undefined {
struct Integer { struct Integer {
type_t type; type_t type;
int _value;
int_t _value;
}; };
struct String { struct String {
@ -126,10 +138,17 @@ const oop null = &_null;
int is(type_t type, oop obj); int is(type_t type, oop obj);
#if (USE_TAG)
int isTag(oop obj)
{
return ((intptr_t)obj & 1);
}
#endif
int isInteger(oop obj) int isInteger(oop obj)
{ {
#if (USE_TAG) #if (USE_TAG)
return (intptr_t)obj & 1;
return ((intptr_t)obj & 1) || is(Integer, obj);
#else #else
return is(Integer, obj); return is(Integer, obj);
#endif #endif
@ -164,15 +183,6 @@ oop _checkType(oop ptr, type_t type, char *file, int line)
#define get(PTR, TYPE, FIELD) (_checkType(PTR, TYPE, __FILE__, __LINE__)->TYPE.FIELD) #define get(PTR, TYPE, FIELD) (_checkType(PTR, TYPE, __FILE__, __LINE__)->TYPE.FIELD)
#define set(PTR, TYPE, FIELD, VALUE) (_checkType(PTR, TYPE, __FILE__, __LINE__)->TYPE.FIELD = VALUE) #define set(PTR, TYPE, FIELD, VALUE) (_checkType(PTR, TYPE, __FILE__, __LINE__)->TYPE.FIELD = VALUE)
void *memcheck(void *ptr)
{
if (NULL == ptr) {
fprintf(stderr, "Error: out of memory\n");
exit(EX_OSERR); // this is as close as we have for 'resource unavailable'
}
return ptr;
}
#include "buffer.h" #include "buffer.h"
DECLARE_STRING_BUFFER(char, StringBuffer); DECLARE_STRING_BUFFER(char, StringBuffer);
@ -180,106 +190,93 @@ void print(oop ast);
void println(oop ast); void println(oop ast);
void printOn(StringBuffer *buf, oop obj, int indent); void printOn(StringBuffer *buf, oop obj, int indent);
int getInteger(oop obj)
int_t getInteger(oop obj)
{ {
#if (USE_TAG)
if (isTag(obj)) return (intptr_t)obj >> 1;
#endif
if (!isInteger(obj)) { if (!isInteger(obj)) {
fprintf(stderr, "\nNon-integer in arithmetic expression\n");
fprintf(stderr, "\nNon-integer in arithmetic expression\n");
exit(1); exit(1);
} }
#if (USE_TAG)
return (intptr_t)obj >> 1;
#else
return get(obj, Integer, _value); return get(obj, Integer, _value);
#endif
} }
oop makeInteger(int value)
#if (USE_TAG)
int isIntegerValue(int_t value)
{
return (((intptr_t)value << 1) >> 1) == value;
// return -32 <= value && value < 32;
}
#endif
oop makeInteger(int_t value)
{ {
#if (USE_TAG) #if (USE_TAG)
return (oop) (((intptr_t)value << 1) | 1);
#else
oop newInt = memcheck(malloc(sizeof(union object)));
if (isIntegerValue(value)) return (oop)(((intptr_t)value << 1) | 1);
#endif
oop newInt = malloc(sizeof(union object));
newInt->type = Integer; newInt->type = Integer;
newInt->Integer._value = value; newInt->Integer._value = value;
return newInt; return newInt;
#endif
} }
// value will be copied
oop makeString(char *value) oop makeString(char *value)
{ {
oop newString = memcheck(malloc(sizeof(union object)));
oop newString = malloc(sizeof(union object));
newString->type = String; newString->type = String;
newString->String.value = memcheck(strdup(value));
newString->String.value = strdup(value);
newString->String.size = strlen(value); newString->String.size = strlen(value);
return newString; return newString;
} }
// value will be used directly
oop makeStringFrom(char *value, size_t l)
{
oop newString = memcheck(malloc(sizeof(union object)));
newString->type = String;
newString->String.value = value;
newString->String.size = l;
return newString;
}
size_t string_size(oop s) size_t string_size(oop s)
{ {
return get(s, String, size); return get(s, String, size);
} }
oop string_slice(oop str, ssize_t start, ssize_t stop) {
assert(is(String, str));
size_t len = string_size(str);
if (start < 0) start= start + len;
if (stop < 0) stop= stop + len;
if (start < 0 || start > len) return NULL;
if (stop < 0 || stop > len) return NULL;
if (start > stop) return NULL;
size_t cpylen = stop - start;
char *slice= memcheck(malloc(sizeof(char) * (cpylen + 1)));
memcpy(slice, get(str, String, value) + start, cpylen);
slice[cpylen]= '\0';
return makeStringFrom(slice, cpylen);
}
oop string_concat(oop str1, oop str2) oop string_concat(oop str1, oop str2)
{ {
size_t len = string_size(str1) + string_size(str2); size_t len = string_size(str1) + string_size(str2);
char *concat = memcheck(malloc(sizeof(char) * len + 1));
char *concat = malloc(sizeof(char) * len + 1);
memcpy(concat, get(str1, String, value), string_size(str1)); memcpy(concat, get(str1, String, value), string_size(str1));
memcpy(concat + string_size(str1), get(str2, String, value), string_size(str2)); memcpy(concat + string_size(str1), get(str2, String, value), string_size(str2));
concat[len]= '\0'; concat[len]= '\0';
return makeStringFrom(concat, len);
oop newString = malloc(sizeof(union object));
newString->type = String;
newString->String.value = concat;
newString->String.size = len;
return newString;
} }
oop string_mul(oop str, oop factor) oop string_mul(oop str, oop factor)
{ {
ssize_t len = string_size(str) * getInteger(factor); ssize_t len = string_size(str) * getInteger(factor);
if (len < 0) len = 0; if (len < 0) len = 0;
char *concat = memcheck(malloc(sizeof(char) * len + 1));
char *concat = malloc(sizeof(char) * len + 1);
for (int i=0; i < getInteger(factor); ++i) { for (int i=0; i < getInteger(factor); ++i) {
memcpy(concat + (i * string_size(str)), get(str, String, value), string_size(str)); memcpy(concat + (i * string_size(str)), get(str, String, value), string_size(str));
} }
concat[len]= '\0'; concat[len]= '\0';
return makeStringFrom(concat, len);
oop newString = malloc(sizeof(union object));
newString->type = String;
newString->String.value = concat;
newString->String.size = len;
return newString;
} }
oop makeSymbol(char *name) oop makeSymbol(char *name)
{ {
oop newSymb = memcheck(malloc(sizeof(union object)));
oop newSymb = malloc(sizeof(union object));
newSymb->type = Symbol; newSymb->type = Symbol;
newSymb->Symbol.name = memcheck(strdup(name));
newSymb->Symbol.name = strdup(name);
newSymb->Symbol.prototype = 0; newSymb->Symbol.prototype = 0;
return newSymb; return newSymb;
} }
oop makeFunction(primitive_t primitive, oop name, oop param, oop body, oop parentScope, oop fixed) oop makeFunction(primitive_t primitive, oop name, oop param, oop body, oop parentScope, oop fixed)
{ {
oop newFunc = memcheck(malloc(sizeof(union object)));
oop newFunc = malloc(sizeof(union object));
newFunc->type = Function; newFunc->type = Function;
newFunc->Function.primitive = primitive; newFunc->Function.primitive = primitive;
newFunc->Function.name = name; newFunc->Function.name = name;
@ -292,7 +289,7 @@ oop makeFunction(primitive_t primitive, oop name, oop param, oop body, oop paren
oop makeMap() oop makeMap()
{ {
oop newMap = memcheck(malloc(sizeof(union object)));
oop newMap = malloc(sizeof(union object));
newMap->type = Map; newMap->type = Map;
return newMap; return newMap;
} }
@ -386,7 +383,7 @@ oop map_insert(oop map, oop key, oop value, size_t pos)
// check capacity and expand if needed // check capacity and expand if needed
if (map_size(map) >= get(map, Map, capacity)) { if (map_size(map) >= get(map, Map, capacity)) {
size_t newCapacity = get(map, Map, capacity) + MAP_CHUNK_SIZE; size_t newCapacity = get(map, Map, capacity) + MAP_CHUNK_SIZE;
set(map, Map, elements, memcheck(realloc(get(map, Map, elements), sizeof(struct Pair) * newCapacity)));
set(map, Map, elements, realloc(get(map, Map, elements), sizeof(struct Pair) * newCapacity));
set(map, Map, capacity, newCapacity); set(map, Map, capacity, newCapacity);
} }
@ -478,26 +475,6 @@ oop map_values(oop map)
return values; return values;
} }
oop map_slice(oop map, ssize_t start, ssize_t stop) {
assert(is(Map, map));
size_t len = map_size(map);
if (start < 0) start= start + len;
if (stop < 0) stop= stop + len;
if (start < 0 || start > len) return NULL;
if (stop < 0 || stop > len) return NULL;
if (start > stop) return NULL;
oop slice= makeMap();
if (start < stop) {
if (!map_hasIntegerKey(map, start )) return NULL;
if (!map_hasIntegerKey(map, stop - 1)) return NULL;
for (size_t i= start; i < stop; ++i) {
map_append(slice, get(map, Map, elements)[i].value);
}
}
return slice;
}
DECLARE_BUFFER(oop, OopStack); DECLARE_BUFFER(oop, OopStack);
OopStack printing = BUFFER_INITIALISER; OopStack printing = BUFFER_INITIALISER;
@ -573,8 +550,8 @@ void printOn(StringBuffer *buf, oop obj, int indent)
return; return;
} }
case Integer: { case Integer: {
char tmp[32];
int length = snprintf(tmp, sizeof(tmp), "%i", getInteger(obj));
char tmp[40];
int length = snprintf(tmp, sizeof(tmp), FMT_I, getInteger(obj));
StringBuffer_appendAll(buf, tmp, length); StringBuffer_appendAll(buf, tmp, length);
return; return;
} }
@ -596,7 +573,7 @@ void printOn(StringBuffer *buf, oop obj, int indent)
printOn(buf, get(obj, Function, name), indent); printOn(buf, get(obj, Function, name), indent);
StringBuffer_append(buf, '('); StringBuffer_append(buf, '(');
printOn(buf, get(obj, Function, param), indent + 1); printOn(buf, get(obj, Function, param), indent + 1);
if (get(obj, Function, param) != null) {
if (is(Map, get(obj, Function, param)) && map_size(get(obj, Function, param)) > 0) {
StringBuffer_append(buf, '\n'); StringBuffer_append(buf, '\n');
indentOn(buf, indent); indentOn(buf, indent);
} }

+ 224
- 340
parse.leg Прегледај датотеку

@ -6,19 +6,19 @@
* run: echo "3+4" | ./parse * run: echo "3+4" | ./parse
*/ */
#define DO_PROTOS() \
_DO(If) _DO(While) _DO(Do) _DO(For) _DO(Switch) _DO(Call) _DO(Invoke) _DO(Func) _DO(Block) \
_DO(Declaration) _DO(Assign) \
_DO(Map) _DO(Symbol) _DO(Integer) _DO(String) \
_DO(Logor) _DO(Logand) _DO(Bitor) _DO(Bitxor) _DO(Bitand) \
_DO(Equal) _DO(Noteq) _DO(Less) _DO(Lesseq) _DO(Greater) _DO(Greatereq) _DO(Shleft) _DO(Shright) \
_DO(Add) _DO(Sub) _DO(Mul) _DO(Div) _DO(Mod) _DO(Not) _DO(Neg) _DO(Com) \
_DO(PreIncVariable) _DO(PreIncMember) _DO(PreIncIndex) \
_DO(PostIncVariable) _DO(PostIncMember) _DO(PostIncIndex) \
_DO(PreDecVariable) _DO(PreDecMember) _DO(PreDecIndex) \
_DO(PostDecVariable) _DO(PostDecMember) _DO(PostDecIndex) \
_DO(GetVariable) _DO(GetMember) _DO(SetMember) _DO(GetIndex) _DO(SetIndex) _DO(Slice) \
_DO(Return) _DO(Break) _DO(Continue) _DO(Throw) _DO(Try) \
#define DO_PROTOS() \
_DO(If) _DO(While) _DO(Do) _DO(For) _DO(ForIn) _DO(Switch) _DO(Call) \
_DO(Invoke) _DO(Func) _DO(Block) _DO(Declaration) _DO(Assign) \
_DO(Map) _DO(Symbol) _DO(Integer) _DO(String) \
_DO(Logor) _DO(Logand) _DO(Bitor) _DO(Bitxor) _DO(Bitand) \
_DO(Equal) _DO(Noteq) _DO(Less) _DO(Lesseq) _DO(Greater) _DO(Greatereq) _DO(Shleft) _DO(Shright) \
_DO(Add) _DO(Sub) _DO(Mul) _DO(Div) _DO(Mod) _DO(Not) _DO(Neg) _DO(Com) \
_DO(PreIncVariable) _DO(PreIncMember) _DO(PreIncIndex) \
_DO(PostIncVariable) _DO(PostIncMember) _DO(PostIncIndex) \
_DO(PreDecVariable) _DO(PreDecMember) _DO(PreDecIndex) \
_DO(PostDecVariable) _DO(PostDecMember) _DO(PostDecIndex) \
_DO(GetVariable) _DO(GetMember) _DO(SetMember) _DO(GetIndex) _DO(SetIndex) \
_DO(Return) _DO(Break) _DO(Continue) _DO(Throw) _DO(Try) \
_DO(Quasiquote) _DO(Unquote) _DO(Quasiquote) _DO(Unquote)
typedef enum { typedef enum {
@ -51,7 +51,7 @@ typedef struct jb_record
jb_record *jbs= NULL; jb_record *jbs= NULL;
jb_record *jbRecPush() { jb_record *jbRecPush() {
jb_record *newJbRec = memcheck(malloc(sizeof(jb_record)));
jb_record *newJbRec = malloc(sizeof(jb_record));
newJbRec->result = null; newJbRec->result = null;
newJbRec->next = jbs; newJbRec->next = jbs;
jbs = newJbRec; jbs = newJbRec;
@ -75,8 +75,7 @@ oop globals= 0;
_DO(lhs) _DO(rhs) _DO(scope) _DO(args) _DO(expression) _DO(labels) _DO(statements) _DO(initialise) \ _DO(lhs) _DO(rhs) _DO(scope) _DO(args) _DO(expression) _DO(labels) _DO(statements) _DO(initialise) \
_DO(update) _DO(this) _DO(fixed) _DO(operator) _DO(map) _DO(func) \ _DO(update) _DO(this) _DO(fixed) _DO(operator) _DO(map) _DO(func) \
_DO(try) _DO(catch) _DO(finally) _DO(exception) \ _DO(try) _DO(catch) _DO(finally) _DO(exception) \
_DO(__line__) _DO(__file__) \
_DO(start) _DO(stop)
_DO(__line__) _DO(__file__)
#define _DO(NAME) oop NAME##_symbol; #define _DO(NAME) oop NAME##_symbol;
DO_SYMBOLS() DO_SYMBOLS()
@ -89,6 +88,8 @@ DO_PROTOS()
int opt_v= 0; int opt_v= 0;
oop mrAST= &_null; oop mrAST= &_null;
void printBacktrace(oop top);
typedef struct input_t typedef struct input_t
{ {
oop name; oop name;
@ -110,7 +111,7 @@ void inputStackPush(char *name) {
} else { } else {
name= "<stdin>"; name= "<stdin>";
} }
input_t *input = memcheck(malloc(sizeof(input_t)));
input_t *input = malloc(sizeof(input_t));
input->name= makeString(name); input->name= makeString(name);
input->lineNumber= 1; input->lineNumber= 1;
input->file= file; input->file= file;
@ -176,9 +177,6 @@ oop getVariable(oop object, oop key)
while (!map_hasKey(object, key)) { while (!map_hasKey(object, key)) {
object = map_get(object, __proto___symbol); object = map_get(object, __proto___symbol);
if (null == object) { if (null == object) {
printf("\nUndefined: ");
println(key);
exit(1);
return null; return null;
} }
} }
@ -203,6 +201,7 @@ oop getMember(oop object, oop key)
if (!map_hasKey(object, key)) { if (!map_hasKey(object, key)) {
printf("\nUndefined: ."); printf("\nUndefined: .");
println(key); println(key);
printBacktrace(mrAST);
exit(1); exit(1);
return null; return null;
} }
@ -259,6 +258,15 @@ oop newFor(oop init, oop cond, oop step, oop body)
return obj; return obj;
} }
oop newForIn(oop name, oop expression, oop body)
{
oop obj= newObject(ForIn_proto);
map_set(obj, name_symbol, name);
map_set(obj, expression_symbol, expression);
map_set(obj, body_symbol, body);
return obj;
}
oop newSwitch(oop expression, oop labels, oop statements) oop newSwitch(oop expression, oop labels, oop statements)
{ {
oop obj= newObject(Switch_proto); oop obj= newObject(Switch_proto);
@ -486,7 +494,7 @@ oop newFunc(oop name, oop param, oop body, oop fixed)
return func; return func;
} }
oop apply(oop scope, oop func, oop args);
oop apply(oop scope, oop this, oop func, oop args, oop ast);
oop getSyntaxId(int n, oop key) oop getSyntaxId(int n, oop key)
{ {
@ -548,15 +556,6 @@ oop newContinue(void)
return obj; return obj;
} }
oop newSlice(oop value, oop start, oop stop)
{
oop obj= newObject(Slice_proto);
map_set(obj, value_symbol, value);
map_set(obj, start_symbol, start);
map_set(obj, stop_symbol, stop);
return obj;
}
oop newTry(oop try, oop exception, oop catch, oop finally) oop newTry(oop try, oop exception, oop catch, oop finally)
{ {
oop obj = newObject(Try_proto); oop obj = newObject(Try_proto);
@ -569,10 +568,10 @@ oop newTry(oop try, oop exception, oop catch, oop finally)
oop fold(oop ast); oop fold(oop ast);
#define YY_INPUT(buf, result, max_size) \
{ \
int yyc= getc(inputStack->file); \
result= (EOF == yyc) ? 0 : (*(buf)= yyc, 1); \
#define YY_INPUT(buf, result, max_size) \
{ \
int yyc= feof(inputStack->file) ? EOF : getc(inputStack->file); \
result= (EOF == yyc) ? 0 : (*(buf)= yyc, 1); \
} }
#define YYSTYPE oop #define YYSTYPE oop
@ -596,6 +595,7 @@ int yyparsefrom(int (*yystart)(struct _yycontext *yy));
%} %}
start = - ( IMPORT s:STRING { yylval = null; inputStackPush(get(s, String, value)) } start = - ( IMPORT s:STRING { yylval = null; inputStackPush(get(s, String, value)) }
| e:exp ';' { yylval = e }
| e:stmt { yylval = e } | e:stmt { yylval = e }
| !. { yylval = 0 } | !. { yylval = 0 }
| error | error
@ -608,7 +608,7 @@ stmt = e:exp SEMICOLON* { $$ = e }
| s:block { $$ = s } | s:block { $$ = s }
block = LCB m:makeMap block = LCB m:makeMap
( s:stmt { map_append(m, s) }
( s:stmt { map_append(m, s) }
) * ) *
RCB { $$ = newBlock(m) } RCB { $$ = newBlock(m) }
@ -624,6 +624,7 @@ exp = VAR l:ident ASSIGN e:exp { $$ = newDeclarati
| IF LPAREN c:exp RPAREN t:stmt { $$ = newIf(c, t, null) } | IF LPAREN c:exp RPAREN t:stmt { $$ = newIf(c, t, null) }
| WHILE LPAREN c:exp RPAREN s:stmt { $$ = newWhile(c, s) } | WHILE LPAREN c:exp RPAREN s:stmt { $$ = newWhile(c, s) }
| DO s:stmt WHILE LPAREN c:exp RPAREN { $$ = newDo(s, c) } | DO s:stmt WHILE LPAREN c:exp RPAREN { $$ = newDo(s, c) }
| FOR LPAREN i:ident IN e:exp RPAREN s:stmt { $$ = newForIn(i, e, s) }
| FOR LPAREN i:stmt c:stmt u:exp RPAREN s:stmt { $$ = newFor(i, c, u, s) } | FOR LPAREN i:stmt c:stmt u:exp RPAREN s:stmt { $$ = newFor(i, c, u, s) }
| s:switch { $$ = s } | s:switch { $$ = s }
| RETURN e:exp { $$ = newReturn(e) } | RETURN e:exp { $$ = newReturn(e) }
@ -635,7 +636,7 @@ exp = VAR l:ident ASSIGN e:exp { $$ = newDeclarati
| l:IDENT o:assignOp e:exp { $$ = newAssign(Assign_proto, l, o, e) } | l:IDENT o:assignOp e:exp { $$ = newAssign(Assign_proto, l, o, e) }
| l:postfix DOT i:IDENT o:assignOp e:exp { $$ = newSetMap(SetMember_proto, l, i, o, e) } | l:postfix DOT i:IDENT o:assignOp e:exp { $$ = newSetMap(SetMember_proto, l, i, o, e) }
| l:postfix LBRAC i:exp RBRAC o:assignOp e:exp { $$ = newSetMap(SetIndex_proto, l, i, o, e) } | l:postfix LBRAC i:exp RBRAC o:assignOp e:exp { $$ = newSetMap(SetIndex_proto, l, i, o, e) }
| l:syntax2 a:argumentList s:block { $$ = (map_append(a, s), apply(globals, l, a)) }
| l:syntax2 a:argumentList s:block { $$ = (map_append(a, s), apply(globals, globals, l, a, a)) }
| c:cond { $$ = c } | c:cond { $$ = c }
ident = l:IDENT { $$ = l } ident = l:IDENT { $$ = l }
@ -674,24 +675,24 @@ cond = c:logor QUERY t:exp COLON f:cond { $$ = newIf(c, t,
| logor | logor
logor = l:logand logor = l:logand
( LOGOR r:logand { l = newBinary(Logor_proto, l, r) }
)* { $$ = l }
( LOGOR r:logand { l = newBinary(Logor_proto, l, r) }
)* { $$ = l }
logand = l:bitor logand = l:bitor
( LOGAND r:bitor { l = newBinary(Logand_proto, l, r) }
)* { $$ = l }
( LOGAND r:bitor { l = newBinary(Logand_proto, l, r) }
)* { $$ = l }
bitor = l:bitxor bitor = l:bitxor
( BITOR r:bitxor { l = newBinary(Bitor_proto, l, r) }
)* { $$ = l }
( BITOR r:bitxor { l = newBinary(Bitor_proto, l, r) }
)* { $$ = l }
bitxor = l:bitand bitxor = l:bitand
( BITXOR r:bitand { l = newBinary(Bitxor_proto, l, r) }
)* { $$ = l }
( BITXOR r:bitand { l = newBinary(Bitxor_proto, l, r) }
)* { $$ = l }
bitand = l:eq bitand = l:eq
( BITAND r:eq { l = newBinary(Bitand_proto, l, r) }
)* { $$ = l }
( BITAND r:eq { l = newBinary(Bitand_proto, l, r) }
)* { $$ = l }
eq = l:ineq eq = l:ineq
( EQUAL r:ineq { l = newBinary(Equal_proto, l, r) } ( EQUAL r:ineq { l = newBinary(Equal_proto, l, r) }
@ -711,8 +712,8 @@ shift = l:sum
)* { $$ = l } )* { $$ = l }
sum = l:prod sum = l:prod
( PLUS r:prod { l = newBinary(Add_proto, l, r) }
| MINUS r:prod { l = newBinary(Sub_proto, l, r) }
( PLUS r:prod { l = newBinary(Add_proto, l, r) }
| MINUS r:prod { l = newBinary(Sub_proto, l, r) }
)* { $$ = l } )* { $$ = l }
prod = l:prefix prod = l:prefix
@ -733,12 +734,8 @@ prefix = PLUS n:prefix { $$= n }
postfix = i:value ( DOT s:IDENT a:argumentList { i = newInvoke(i, s, a) } postfix = i:value ( DOT s:IDENT a:argumentList { i = newInvoke(i, s, a) }
| DOT s:IDENT !assignOp { i = newGetMap(GetMember_proto, i, s) } | DOT s:IDENT !assignOp { i = newGetMap(GetMember_proto, i, s) }
| LBRAC e1:exp COLON e2:exp RBRAC !assignOp { i = newSlice(i, e1, e2) }
| LBRAC e1:exp COLON RBRAC !assignOp { i = newSlice(i, e1, null) }
| LBRAC COLON e2:exp RBRAC !assignOp { i = newSlice(i, null, e2) }
| LBRAC COLON RBRAC !assignOp { i = newSlice(i, null, null) }
| LBRAC p:exp RBRAC !assignOp { i = newGetMap(GetIndex_proto, i, p) } | LBRAC p:exp RBRAC !assignOp { i = newGetMap(GetIndex_proto, i, p) }
| a:argumentList { i = (null != getSyntax(1, i)) ? apply(globals, getSyntax(1, i), a) : newCall(i, a) }
| a:argumentList { i = (null != getSyntax(1, i)) ? apply(globals, globals, getSyntax(1, i), a, i) : newCall(i, a) }
| PLUSPLUS { i = newPostIncrement(i) } | PLUSPLUS { i = newPostIncrement(i) }
| MINUSMINUS { i = newPostDecrement(i) } | MINUSMINUS { i = newPostDecrement(i) }
) * { $$ = i } ) * { $$ = i }
@ -764,6 +761,7 @@ value = n:NUMBER { $$ = newInteger(n) }
| NULL { $$ = null } | NULL { $$ = null }
| i:IDENT { $$ = newGetVariable(i) } | i:IDENT { $$ = newGetVariable(i) }
| LPAREN i:stmt RPAREN { $$ = i } | LPAREN i:stmt RPAREN { $$ = i }
| b:block { $$ = b }
string = s:STRING - { $$ = s } string = s:STRING - { $$ = s }
@ -800,10 +798,10 @@ eol = ( "\n""\r"*
| "\r""\n"* | "\r""\n"*
) { inputStack->lineNumber++ } ) { inputStack->lineNumber++ }
comment = "//" ( ![\n\r] . )*
| "/*" ( !"*/" . )* "*/"
comment = "//" ( ![\n\r] . )*
| "/*" ( !"*/" (eol | .) )* "*/"
keyword = FUN | SYNTAX | VAR | SWITCH | CASE | DEFAULT | DO | FOR | WHILE | IF | ELSE | NULL | RETURN | BREAK | CONTINUE
keyword = FUN | SYNTAX | VAR | SWITCH | CASE | DEFAULT | DO | FOR | IN | WHILE | IF | ELSE | NULL | RETURN | BREAK | CONTINUE
| THROW | TRY | CATCH | FINALLY | THROW | TRY | CATCH | FINALLY
IDENT = !keyword < [a-zA-Z_][a-zA-Z0-9_]* > - { $$ = intern(yytext) } IDENT = !keyword < [a-zA-Z_][a-zA-Z0-9_]* > - { $$ = intern(yytext) }
@ -822,6 +820,7 @@ CASE = 'case' ![a-zA-Z0-9_] -
DEFAULT = 'default' ![a-zA-Z0-9_] - DEFAULT = 'default' ![a-zA-Z0-9_] -
DO = 'do' ![a-zA-Z0-9_] - DO = 'do' ![a-zA-Z0-9_] -
FOR = 'for' ![a-zA-Z0-9_] - FOR = 'for' ![a-zA-Z0-9_] -
IN = 'in' ![a-zA-Z0-9_] -
WHILE = 'while' ![a-zA-Z0-9_] - WHILE = 'while' ![a-zA-Z0-9_] -
IF = 'if' ![a-zA-Z0-9_] - IF = 'if' ![a-zA-Z0-9_] -
ELSE = 'else' ![a-zA-Z0-9_] - ELSE = 'else' ![a-zA-Z0-9_] -
@ -946,7 +945,7 @@ void trace(oop ast, oop func)
void untrace(oop ast) void untrace(oop ast)
{ {
struct Call top= CallArray_pop(&backtrace); assert(top.ast == ast);
struct Call top= CallArray_pop(&backtrace); assert(top.ast == ast);
} }
void printLocation(oop ast) void printLocation(oop ast)
@ -1067,30 +1066,37 @@ oop fold(oop ast)
if (isFalse(fold(rhs))) return makeInteger(0); if (isFalse(fold(rhs))) return makeInteger(0);
return makeInteger(1); return makeInteger(1);
} }
# define BINARY(NAME, OPERATOR) \
# define RELATION(NAME, OPERATOR) \
case t_##NAME: { \
oop lhs= fold(map_get(ast, lhs_symbol)); \
oop rhs= fold(map_get(ast, rhs_symbol)); \
return makeInteger(oopcmp(lhs, rhs) OPERATOR 0); \
}
# define BINARY(NAME, OPERATOR) \
case t_##NAME: { \ case t_##NAME: { \
oop lhs= fold(map_get(ast, lhs_symbol)); \ oop lhs= fold(map_get(ast, lhs_symbol)); \
oop rhs= fold(map_get(ast, rhs_symbol)); \ oop rhs= fold(map_get(ast, rhs_symbol)); \
return makeInteger(getInteger(lhs) OPERATOR getInteger(rhs)); \ return makeInteger(getInteger(lhs) OPERATOR getInteger(rhs)); \
} }
BINARY(Bitor, | );
BINARY(Bitxor, ^ );
BINARY(Bitand, & );
BINARY(Equal, ==);
BINARY(Noteq, !=);
BINARY(Less, < );
BINARY(Lesseq, <=);
BINARY(Greatereq, >=);
BINARY(Greater, > );
BINARY(Shleft, <<);
BINARY(Shright, >>);
BINARY(Add, + );
BINARY(Sub, - );
BINARY(Mul, * );
BINARY(Div, / );
BINARY(Mod, % );
# undef BINARY
# define UNARY(NAME, OPERATOR) \
BINARY(Bitor, | );
BINARY(Bitxor, ^ );
BINARY(Bitand, & );
RELATION(Equal, ==);
RELATION(Noteq, !=);
RELATION(Less, < );
RELATION(Lesseq, <=);
RELATION(Greatereq, >=);
RELATION(Greater, > );
BINARY(Shleft, <<);
BINARY(Shright, >>);
BINARY(Add, + );
BINARY(Sub, - );
BINARY(Mul, * );
BINARY(Div, / );
BINARY(Mod, % );
# undef BINARY
# undef RELATION
# define UNARY(NAME, OPERATOR) \
case t_##NAME: { \ case t_##NAME: { \
oop rhs = fold(map_get(ast, rhs_symbol)); \ oop rhs = fold(map_get(ast, rhs_symbol)); \
return makeInteger(OPERATOR getInteger(rhs)); \ return makeInteger(OPERATOR getInteger(rhs)); \
@ -1098,7 +1104,7 @@ oop fold(oop ast)
UNARY(Not, !); UNARY(Not, !);
UNARY(Neg, -); UNARY(Neg, -);
UNARY(Com, ~); UNARY(Com, ~);
# undef UNARY
# undef UNARY
default: default:
break; break;
} }
@ -1113,28 +1119,71 @@ oop fold(oop ast)
oop applyOperator(oop ast, oop op, oop lhs, oop rhs) oop applyOperator(oop ast, oop op, oop lhs, oop rhs)
{ {
if (null != op) { assert(is(Symbol, op)); if (null != op) { assert(is(Symbol, op));
switch (get(op, Symbol, prototype)) {
case t_Add: return addOperation(ast, lhs, rhs);
case t_Sub: return makeInteger(getInteger(lhs) - getInteger(rhs));
case t_Mul: return mulOperation(ast, lhs, rhs);
case t_Div: return makeInteger(getInteger(lhs) / getInteger(rhs));
case t_Mod: return makeInteger(getInteger(lhs) % getInteger(rhs));
case t_Bitor: return makeInteger(getInteger(lhs) | getInteger(rhs));
case t_Bitxor: return makeInteger(getInteger(lhs) ^ getInteger(rhs));
case t_Bitand: return makeInteger(getInteger(lhs) & getInteger(rhs));
case t_Shleft: return makeInteger(getInteger(lhs) << getInteger(rhs));
case t_Shright: return makeInteger(getInteger(lhs) >> getInteger(rhs));
default: {
fprintf(stderr, "\nIllegal operator %i\n", get(op, Symbol, prototype));
exit(1);
switch (get(op, Symbol, prototype)) {
case t_Add: return addOperation(ast, lhs, rhs);
case t_Sub: return makeInteger(getInteger(lhs) - getInteger(rhs));
case t_Mul: return mulOperation(ast, lhs, rhs);
case t_Div: return makeInteger(getInteger(lhs) / getInteger(rhs));
case t_Mod: return makeInteger(getInteger(lhs) % getInteger(rhs));
case t_Bitor: return makeInteger(getInteger(lhs) | getInteger(rhs));
case t_Bitxor: return makeInteger(getInteger(lhs) ^ getInteger(rhs));
case t_Bitand: return makeInteger(getInteger(lhs) & getInteger(rhs));
case t_Shleft: return makeInteger(getInteger(lhs) << getInteger(rhs));
case t_Shright: return makeInteger(getInteger(lhs) >> getInteger(rhs));
default: {
fprintf(stderr, "\nIllegal operator %i\n", get(op, Symbol, prototype));
exit(1);
}
} }
} }
}
return rhs; return rhs;
} }
oop evalArgs(oop scope, oop args); oop evalArgs(oop scope, oop args);
oop apply(oop scope, oop this, oop func, oop args, oop ast)
{
assert(is(Function, func));
if (NULL != get(func, Function, primitive)) {
return get(func, Function, primitive)(scope, args);
}
oop param = get(func, Function, param);
oop localScope = map_zip(param, args);
map_set(localScope, this_symbol, this);
map_set(localScope, __arguments___symbol, args);
map_set(localScope, __proto___symbol, get(func, Function, parentScope));
jbRecPush();
trace(ast, func);
int jbt = sigsetjmp(jbs->jb, 0);
switch (jbt) {
case j_return: {
untrace(ast);
oop result = jbs->result;
jbRecPop();
return result;
}
case j_break: {
runtimeError("break outside of a loop or switch");
}
case j_continue: {
runtimeError("continue outside of a loop");
}
case j_throw: {
untrace(ast);
oop res= jbs->result;
jbRecPop();
jbs->result= res;
siglongjmp(jbs->jb, j_throw);
}
}
oop result= eval(localScope, get(func, Function, body));
untrace(ast);
jbRecPop();
return result;
}
oop eval(oop scope, oop ast) oop eval(oop scope, oop ast)
{ {
if (opt_v > 3) { if (opt_v > 3) {
@ -1280,7 +1329,7 @@ oop eval(oop scope, oop ast)
} }
case j_break: { case j_break: {
jbRecPop(); jbRecPop();
return null;
return result;
} }
case j_continue: { case j_continue: {
goto restart_for; goto restart_for;
@ -1294,6 +1343,40 @@ oop eval(oop scope, oop ast)
jbRecPop(); jbRecPop();
return result; return result;
} }
case t_ForIn: {
oop expr = eval(scope, map_get(ast, expression_symbol)); if (!is(Map, expr)) return null;
oop name = map_get(ast, name_symbol ) ;
oop body = map_get(ast, body_symbol ) ;
oop result = null;
oop localScope = newObject(scope);
jbRecPush();
int jbt = sigsetjmp(jbs->jb, 0);
switch (jbt) {
case j_return:
case j_throw: {
oop result = jbs->result;
jbRecPop();
assert(jbs);
jbs->result = result;
siglongjmp(jbs->jb, jbt);
assert(0);
}
case j_break: {
jbRecPop();
return result;
}
case j_continue: {
goto restart_forin;
}
}
for (size_t i= 0; i < map_size(expr); ++i) {
map_set(localScope, name, get(expr, Map, elements)[i].key);
result= eval(localScope, body);
restart_forin:;
}
jbRecPop();
return result;
}
case t_Switch: { case t_Switch: {
oop expression = map_get(ast, expression_symbol ); oop expression = map_get(ast, expression_symbol );
oop labels = map_get(ast, labels_symbol ); oop labels = map_get(ast, labels_symbol );
@ -1369,107 +1452,26 @@ oop eval(oop scope, oop ast)
printBacktrace(ast); printBacktrace(ast);
exit(1); exit(1);
} }
oop args = map_get(ast, args_symbol); oop args = map_get(ast, args_symbol);
if (isFalse(get(func, Function, fixed))) { if (isFalse(get(func, Function, fixed))) {
args = evalArgs(scope, args); args = evalArgs(scope, args);
} }
if (get(func, Function, primitive) == NULL) {
oop param = get(func, Function, param);
oop localScope = map_zip(param, args);
map_set(localScope, __arguments___symbol, args);
map_set(localScope, __proto___symbol, get(func, Function, parentScope));
if (opt_v > 4) {
printf("parentScope: ");
println(get(func, Function, parentScope));
printf("localScope: ");
println(localScope);
}
jbRecPush();
trace(ast, func);
int jbt = sigsetjmp(jbs->jb, 0);
switch (jbt) {
case j_return: {
untrace(ast);
oop result = jbs->result;
jbRecPop();
return result;
}
case j_break: {
runtimeError("break outside of a loop");
}
case j_continue: {
runtimeError("continue outside of a loop");
}
case j_throw: {
untrace(ast);
oop res= jbs->result;
jbRecPop();
jbs->result= res;
siglongjmp(jbs->jb, j_throw);
}
}
oop result = eval(localScope, get(func, Function, body));
untrace(ast);
jbRecPop();
return result;
}
return get(func, Function, primitive)(scope, args);
return apply(scope, globals, func, args, ast);
} }
case t_Invoke: { case t_Invoke: {
// this is what differs from t_call
oop this = eval(scope, map_get(ast, this_symbol)); oop this = eval(scope, map_get(ast, this_symbol));
oop func = getVariable(this, map_get(ast, name_symbol));
oop func = map_get(ast, name_symbol); assert(is(Symbol, func));
func = getVariable(this, func);
if (!is(Function, func)) { if (!is(Function, func)) {
printf("\ncannot invoke %s\n", printString(func)); printf("\ncannot invoke %s\n", printString(func));
printBacktrace(ast); printBacktrace(ast);
exit(1); exit(1);
} }
oop args = evalArgs(scope, map_get(ast, args_symbol));
if (NULL != get(func, Function, primitive)) {
return get(func, Function, primitive)(scope, args);
}
oop param = get(func, Function, param);
oop localScope = map_zip(param, args);
// and set this in the local scope
map_set(localScope, this_symbol, this);
map_set(localScope, __arguments___symbol, args);
map_set(localScope, __proto___symbol, get(func, Function, parentScope));
if (opt_v > 4) {
printf("parentScope: ");
println(get(func, Function, parentScope));
printf("localScope: ");
println(localScope);
}
jbRecPush();
int jbt = sigsetjmp(jbs->jb, 0);
switch (jbt) {
case j_return: {
oop result = jbs->result;
jbRecPop();
return result;
}
case j_break: {
runtimeError("break outside of a loop");
}
case j_continue: {
runtimeError("continue outside of a loop");
}
case j_throw: {
oop res= jbs->result;
jbRecPop();
jbs->result= res;
siglongjmp(jbs->jb, j_throw);
}
oop args = map_get(ast, args_symbol);
if (isFalse(get(func, Function, fixed))) {
args = evalArgs(scope, args);
} }
oop result = eval(localScope, get(func, Function, body));
jbRecPop();
return result;
return apply(scope, this, func, args, ast);
} }
case t_Return: { case t_Return: {
@ -1570,23 +1572,11 @@ oop eval(oop scope, oop ast)
oop key = eval(scope, map_get(ast, key_symbol)); oop key = eval(scope, map_get(ast, key_symbol));
switch (getType(map)) { switch (getType(map)) {
case String: case String:
if (!isInteger(key)) {
runtimeError("non-integer index");
}
ssize_t i= getInteger(key);
size_t len= string_size(map);
if (i < 0) i+= len;
if (i < 0 || i >= len) {
runtimeError("GetIndex out of bounds on String");
if (getInteger(key) >= get(map, String, size)) {
runtimeError("GetIndex out of range on String");
} }
return makeInteger(get(map, String, value)[i]);
return makeInteger(unescape(get(map, String, value))[getInteger(key)]);
case Map: case Map:
if (isInteger(key) && getInteger(key) < 0) {
size_t size= map_size(map);
if (size > 0 && map_hasIntegerKey(map, size - 1)) {
key= makeInteger(getInteger(key) + size);
}
}
return map_get(map, key); return map_get(map, key);
default: default:
runtimeError("GetIndex on non Map or String"); runtimeError("GetIndex on non Map or String");
@ -1600,7 +1590,7 @@ oop eval(oop scope, oop ast)
switch (getType(map)) { switch (getType(map)) {
case String: case String:
if (getInteger(key) >= get(map, String, size)) { if (getInteger(key) >= get(map, String, size)) {
runtimeError("SetIndex out of bounds on String");
runtimeError("SetIndex out of range on String");
} }
get(map, String, value)[getInteger(key)] = getInteger(value); get(map, String, value)[getInteger(key)] = getInteger(value);
return value; return value;
@ -1612,35 +1602,6 @@ oop eval(oop scope, oop ast)
} }
} }
case t_Slice: {
oop pre= eval(scope, map_get(ast, value_symbol));
oop start= eval(scope, map_get(ast, start_symbol));
oop stop= eval(scope, map_get(ast, stop_symbol));
ssize_t first= start == null ? 0 : getInteger(start);
if (start == null) {
start= makeInteger(0);
}
switch (getType(pre)) {
case String: {
ssize_t last= stop == null ? string_size(pre) : getInteger(stop);
oop res= string_slice(pre, first, last);
if (NULL == res) {
runtimeError("index out of bounds");
}
return res;
}
case Map: {
ssize_t last= stop == null ? map_size(pre) : getInteger(stop);
oop res= map_slice(pre, first, last);
if (NULL == res) {
runtimeError("index out of bounds");
}
return res;
}
}
runtimeError("slicing a non-String or non-Map");
}
case t_Symbol: case t_Symbol:
case t_Integer: case t_Integer:
case t_String: { case t_String: {
@ -1660,31 +1621,29 @@ oop eval(oop scope, oop ast)
if (isFalse(eval(scope, rhs))) return makeInteger(0); if (isFalse(eval(scope, rhs))) return makeInteger(0);
return makeInteger(1); return makeInteger(1);
} }
# define RELATION(NAME, OPERATOR) \
case t_##NAME: { \
oop lhs = eval(scope, map_get(ast, lhs_symbol)); \
oop rhs = eval(scope, map_get(ast, rhs_symbol)); \
return makeInteger(oopcmp(lhs, rhs) OPERATOR 0); \
}
# define BINARY(NAME, OPERATOR) \ # define BINARY(NAME, OPERATOR) \
case t_##NAME: { \ case t_##NAME: { \
oop lhs = eval(scope, map_get(ast, lhs_symbol)); \ oop lhs = eval(scope, map_get(ast, lhs_symbol)); \
oop rhs = eval(scope, map_get(ast, rhs_symbol)); \ oop rhs = eval(scope, map_get(ast, rhs_symbol)); \
return makeInteger(getInteger(lhs) OPERATOR getInteger(rhs)); \ return makeInteger(getInteger(lhs) OPERATOR getInteger(rhs)); \
} }
BINARY(Bitor, | );
BINARY(Bitxor, ^ );
BINARY(Bitand, & );
case t_Equal: {
oop lhs = eval(scope, map_get(ast, lhs_symbol));
oop rhs = eval(scope, map_get(ast, rhs_symbol));
return makeInteger(0 == oopcmp(lhs, rhs));
}
case t_Noteq: {
oop lhs = eval(scope, map_get(ast, lhs_symbol));
oop rhs = eval(scope, map_get(ast, rhs_symbol));
return makeInteger(0 != oopcmp(lhs, rhs));
}
BINARY(Less, < );
BINARY(Lesseq, <=);
BINARY(Greatereq, >=);
BINARY(Greater, > );
BINARY(Shleft, <<);
BINARY(Shright, >>);
BINARY(Bitor, | );
BINARY(Bitxor, ^ );
BINARY(Bitand, & );
RELATION(Equal, ==);
RELATION(Noteq, !=);
RELATION(Less, < );
RELATION(Lesseq, <=);
RELATION(Greatereq, >=);
RELATION(Greater, > );
BINARY(Shleft, <<);
BINARY(Shright, >>);
// BINARY(Add, + ); // BINARY(Add, + );
case t_Add: { case t_Add: {
oop lhs = eval(scope, map_get(ast, lhs_symbol)); oop lhs = eval(scope, map_get(ast, lhs_symbol));
@ -1701,6 +1660,7 @@ oop eval(oop scope, oop ast)
BINARY(Div, / ); BINARY(Div, / );
BINARY(Mod, % ); BINARY(Mod, % );
# undef BINARY # undef BINARY
# undef RELATION
case t_Not: { case t_Not: {
oop rhs = eval(scope, map_get(ast, rhs_symbol)); oop rhs = eval(scope, map_get(ast, rhs_symbol));
return makeInteger(isFalse(rhs)); return makeInteger(isFalse(rhs));
@ -1848,94 +1808,18 @@ oop prim_length(oop scope, oop params)
return null; return null;
} }
oop prim_apply(oop scope, oop params) {
oop func= null; if (map_hasIntegerKey(params, 0)) func= get(params, Map, elements)[0].value;
oop args= null; if (map_hasIntegerKey(params, 1)) args= get(params, Map, elements)[1].value;
return apply(scope, globals, func, args, mrAST);
}
oop prim_invoke(oop scope, oop params) oop prim_invoke(oop scope, oop params)
{ {
oop this= null; if (map_hasIntegerKey(params, 0)) this= get(params, Map, elements)[0].value; oop this= null; if (map_hasIntegerKey(params, 0)) this= get(params, Map, elements)[0].value;
oop func= null; if (map_hasIntegerKey(params, 1)) func= get(params, Map, elements)[1].value; oop func= null; if (map_hasIntegerKey(params, 1)) func= get(params, Map, elements)[1].value;
oop args= null; if (map_hasIntegerKey(params, 2)) args= get(params, Map, elements)[2].value; oop args= null; if (map_hasIntegerKey(params, 2)) args= get(params, Map, elements)[2].value;
if (!is(Function, func)) {
printf("\ncannot invoke %s\n", printString(func));
printBacktrace(mrAST);
exit(1);
}
if (NULL != get(func, Function, primitive)) {
return get(func, Function, primitive)(scope, args);
}
oop param = get(func, Function, param);
oop localScope = map_zip(param, args);
map_set(localScope, this_symbol, this);
map_set(localScope, __arguments___symbol, args);
map_set(localScope, __proto___symbol, get(func, Function, parentScope));
jbRecPush();
int jbt = sigsetjmp(jbs->jb, 0);
switch (jbt) {
case j_return: {
oop result = jbs->result;
jbRecPop();
return result;
}
case j_break: {
runtimeError("break outside of a loop or switch");
}
case j_continue: {
runtimeError("continue oustide of a loop");
}
case j_throw: {
oop res= jbs->result;
jbRecPop();
jbs->result= res;
siglongjmp(jbs->jb, j_throw);
}
}
oop result= eval(localScope, get(func, Function, body));
jbRecPop();
return result;
}
oop apply(oop scope, oop func, oop args)
{
if (!is(Function, func)) {
printf("\ncannot apply %s\n", printString(func));
printBacktrace(mrAST);
exit(1);
}
if (NULL != get(func, Function, primitive)) {
return get(func, Function, primitive)(scope, args);
}
oop param = get(func, Function, param);
oop localScope = map_zip(param, args);
map_set(localScope, __arguments___symbol, args);
map_set(localScope, __proto___symbol, get(func, Function, parentScope));
jbRecPush();
int jbt = sigsetjmp(jbs->jb, 0);
switch (jbt) {
case j_return: {
oop result = jbs->result;
jbRecPop();
return result;
}
case j_break: {
runtimeError("break outside of a loop or switch");
}
case j_continue: {
runtimeError("continue outside of a loop");
}
case j_throw: {
oop res= jbs->result;
jbRecPop();
jbs->result= res;
siglongjmp(jbs->jb, j_throw);
}
}
oop result= eval(localScope, get(func, Function, body));
jbRecPop();
return result;
}
oop prim_apply(oop scope, oop params) {
oop func= null; if (map_hasIntegerKey(params, 0)) func= get(params, Map, elements)[0].value;
oop args= null; if (map_hasIntegerKey(params, 1)) args= get(params, Map, elements)[1].value;
return apply(scope, func, args);
return apply(scope, this, func, args, mrAST);
} }
oop prim_clone(oop scope, oop params) oop prim_clone(oop scope, oop params)
@ -2033,11 +1917,11 @@ oop prim_scope(oop scope, oop params)
#include <sys/resource.h> #include <sys/resource.h>
oop prim_millis(oop scope, oop params)
oop prim_microseconds(oop scope, oop params)
{ {
struct rusage ru; struct rusage ru;
getrusage(RUSAGE_SELF, &ru); getrusage(RUSAGE_SELF, &ru);
return makeInteger(ru.ru_utime.tv_sec * 1000 + ru.ru_utime.tv_usec / 1000);
return makeInteger(ru.ru_utime.tv_sec * 1000*1000 + ru.ru_utime.tv_usec);
} }
int main(int argc, char **argv) int main(int argc, char **argv)
@ -2049,16 +1933,16 @@ int main(int argc, char **argv)
symbol_table= makeMap(); symbol_table= makeMap();
globals= makeMap(); globals= makeMap();
map_set(globals, intern("exit") , makeFunction(prim_exit, intern("exit"), null, null, globals, null));
map_set(globals, intern("keys") , makeFunction(prim_keys, intern("keys"), null, null, globals, null));
map_set(globals, intern("values") , makeFunction(prim_values, intern("values"), null, null, globals, null));
map_set(globals, intern("length") , makeFunction(prim_length, intern("length"), null, null, globals, null));
map_set(globals, intern("print") , makeFunction(prim_print, intern("print"), null, null, globals, null));
map_set(globals, intern("invoke") , makeFunction(prim_invoke, intern("invoke"), null, null, globals, null));
map_set(globals, intern("apply") , makeFunction(prim_apply, intern("apply"), null, null, globals, null));
map_set(globals, intern("clone") , makeFunction(prim_clone, intern("clone"), null, null, globals, null));
map_set(globals, intern("import") , makeFunction(prim_import, intern("import"), null, null, globals, null));
map_set(globals, intern("millis") , makeFunction(prim_millis, intern("millis"), null, null, globals, null));
map_set(globals, intern("exit" ), makeFunction(prim_exit, intern("exit" ), null, null, globals, null));
map_set(globals, intern("keys" ), makeFunction(prim_keys, intern("keys" ), null, null, globals, null));
map_set(globals, intern("values" ), makeFunction(prim_values, intern("values" ), null, null, globals, null));
map_set(globals, intern("length" ), makeFunction(prim_length, intern("length" ), null, null, globals, null));
map_set(globals, intern("print" ), makeFunction(prim_print, intern("print" ), null, null, globals, null));
map_set(globals, intern("invoke" ), makeFunction(prim_invoke, intern("invoke" ), null, null, globals, null));
map_set(globals, intern("apply" ), makeFunction(prim_apply, intern("apply" ), null, null, globals, null));
map_set(globals, intern("clone" ), makeFunction(prim_clone, intern("clone" ), null, null, globals, null));
map_set(globals, intern("import" ), makeFunction(prim_import, intern("import" ), null, null, globals, null));
map_set(globals, intern("microseconds"), makeFunction(prim_microseconds, intern("microseconds"), null, null, globals, null));
map_set(globals, intern("scope"), makeFunction(prim_scope, intern("scope"), null, null, globals, null)); map_set(globals, intern("scope"), makeFunction(prim_scope, intern("scope"), null, null, globals, null));

+ 5
- 0
test-error.txt Прегледај датотеку

@ -0,0 +1,5 @@
fun fib(n) {
if (n < 2) "1" else 1 + fib(n-1) + fib(n-2);
}
println(fib(15))

+ 30
- 0
test-namespace.txt Прегледај датотеку

@ -0,0 +1,30 @@
syntax class (name) body {
`{ __name__ = @name;
@body;
scope()
}
}
var ns = {
__name__ = #"testing";
var counter = 0;
fun inc () { ns.counter += 1 };
fun dec () { ns.counter -= 1 };
scope()
};
println(ns.counter);
ns.inc(); println(ns.counter);
ns.inc(); println(ns.counter);
ns.inc(); println(ns.counter);
ns.dec(); println(ns.counter);
ns.dec(); println(ns.counter);
ns.dec(); println(ns.counter);
var obj = { __proto__ = ns; scope() };
obj.inc();
println(obj.counter);

+ 29
- 13
test-object.txt Прегледај датотеку

@ -1,25 +1,25 @@
var Object = { __name__: #"Object" }; var Object = { __name__: #"Object" };
print("Object is ", Object);
println("Object is ", Object);
var Point = { __name__: #"Point", __proto__ : Object }; var Point = { __name__: #"Point", __proto__ : Object };
print("Point is ", Point);
println("Point is ", Point);
Object.new = fun () { Object.new = fun () {
print("ARGS are ", __arguments__);
println("ARGS are ", __arguments__);
var obj= { __proto__ : this }; var obj= { __proto__ : this };
var init= this.init; var init= this.init;
print("INIT is ", init);
println("INIT is ", init);
init && invoke(obj, init, __arguments__); init && invoke(obj, init, __arguments__);
obj; obj;
}; };
print("Object.new is ", Object.new);
println("Object.new is ", Object.new);
print("Point.new is ", Point.new);
println("Point.new is ", Point.new);
print("Object.new() is ", Object.new());
println("Object.new() is ", Object.new());
Point.init = fun (x, y) { Point.init = fun (x, y) {
this.x = x; this.x = x;
@ -28,7 +28,7 @@ Point.init = fun (x, y) {
var p = Point.new(3, 4); var p = Point.new(3, 4);
print("Point.new(3, 4) is ", p);
println("Point.new(3, 4) is ", p);
@ -36,9 +36,9 @@ Object.clone = fun () { clone(this) }
var q = p.clone(); var q = p.clone();
print("clone is ", q);
println("clone is ", q);
Object.println = fun () { this.print(); print(9;\n';); this; }
Object.println = fun () { this.print(); print(4;\n";); this; }
Object.print = fun () { Object.print = fun () {
var proto= this.__proto__; var proto= this.__proto__;
@ -69,7 +69,7 @@ fun println() {
} }
fun makeAst() { fun makeAst() {
print("Making an AST!")
println("Making an AST!")
return t return t
} }
@ -87,10 +87,26 @@ syntax until(c, b) {
return `(while (!@c) @b) return `(while (!@c) @b)
} }
var x = 0
var x = 0;
/* /*
until(x==10) { until(x==10) {
println(x++) println(x++)
} }
*/ */
(`x).println()
println(`x);
AST.__proto__ = Object;
for (key in AST) AST[key].__proto__ = AST;
/*
{
var k= keys(AST);
var n= length(k);
for (i = 0; i < n; ++i)
AST[k[i]].__proto__ = AST;
};
*/
(`x).println();

Loading…
Откажи
Сачувај