|
|
@ -20,9 +20,9 @@ |
|
|
|
_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(GetVariable) _DO(GetMember) _DO(SetMember) _DO(GetIndex) _DO(SetIndex) _DO(Slice) \ |
|
|
|
_DO(Return) _DO(Break) _DO(Continue) _DO(Throw) _DO(Try) \ |
|
|
|
_DO(Quasiquote) _DO(Unquote) |
|
|
|
_DO(Quasiquote) _DO(Unquote) _DO(Unsplice) _DO(Splice) |
|
|
|
|
|
|
|
typedef enum { |
|
|
|
t_UNDEFINED=0, |
|
|
@ -71,7 +71,8 @@ oop globals= 0; |
|
|
|
_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(try) _DO(catch) _DO(finally) _DO(exception) \ |
|
|
|
_DO(__line__) _DO(__file__) |
|
|
|
_DO(__line__) _DO(__file__) \ |
|
|
|
_DO(start) _DO(stop) |
|
|
|
|
|
|
|
#define _DO(NAME) oop NAME##_symbol; |
|
|
|
DO_SYMBOLS() |
|
|
@ -568,6 +569,15 @@ oop newContinue(void) |
|
|
|
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 obj = newObject(Try_proto); |
|
|
@ -650,7 +660,7 @@ exp = VAR l:ident ASSIGN e:exp { $$ = newDeclarati |
|
|
|
| c:cond { $$ = c } |
|
|
|
|
|
|
|
ident = l:IDENT { $$ = l } |
|
|
|
| AT n:prefix { $$ = newUnary(Unquote_proto, n) } |
|
|
|
| AT n:value { $$ = newUnary(Unquote_proto, n) } |
|
|
|
|
|
|
|
syntax2 = < [a-zA-Z_][a-zA-Z0-9_]* > |
|
|
|
&{ null != getSyntaxId(2, intern(yytext)) } - { $$ = getSyntaxId(2, intern(yytext)) } |
|
|
@ -686,23 +696,23 @@ cond = c:logor QUERY t:exp COLON f:cond { $$ = newIf(c, t, |
|
|
|
|
|
|
|
logor = l:logand |
|
|
|
( LOGOR r:logand { l = newBinary(Logor_proto, l, r) } |
|
|
|
)* { $$ = l } |
|
|
|
)* { $$ = l } |
|
|
|
|
|
|
|
logand = l:bitor |
|
|
|
( LOGAND r:bitor { l = newBinary(Logand_proto, l, r) } |
|
|
|
)* { $$ = l } |
|
|
|
)* { $$ = l } |
|
|
|
|
|
|
|
bitor = l:bitxor |
|
|
|
( BITOR r:bitxor { l = newBinary(Bitor_proto, l, r) } |
|
|
|
)* { $$ = l } |
|
|
|
)* { $$ = l } |
|
|
|
|
|
|
|
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 r:eq { l = newBinary(Bitand_proto, l, r) } |
|
|
|
)* { $$ = l } |
|
|
|
( BITAND r:eq { l = newBinary(Bitand_proto, l, r) } |
|
|
|
)* { $$ = l } |
|
|
|
|
|
|
|
eq = l:ineq |
|
|
|
( EQUAL r:ineq { l = newBinary(Equal_proto, l, r) } |
|
|
@ -722,8 +732,8 @@ shift = l:sum |
|
|
|
)* { $$ = l } |
|
|
|
|
|
|
|
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 } |
|
|
|
|
|
|
|
prod = l:prefix |
|
|
@ -738,12 +748,14 @@ prefix = PLUS n:prefix { $$= n } |
|
|
|
| PLING n:prefix { $$= newUnary(Not_proto, n) } |
|
|
|
| PLUSPLUS n:prefix { $$= newPreIncrement(n) } |
|
|
|
| MINUSMINUS n:prefix { $$= newPreDecrement(n) } |
|
|
|
| BACKTICK n:prefix { $$ = newUnary(Quasiquote_proto, n) } |
|
|
|
| AT n:prefix { $$ = newUnary(Unquote_proto, n) } |
|
|
|
| n:postfix { $$= n } |
|
|
|
|
|
|
|
postfix = i:value ( DOT s:IDENT a:argumentList { i = newInvoke(i, s, a) } |
|
|
|
| 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) } |
|
|
|
| a:argumentList { i = (null != getSyntax(1, i)) ? apply(globals, globals, getSyntax(1, i), a, i) : newCall(i, a) } |
|
|
|
| PLUSPLUS { i = newPostIncrement(i) } |
|
|
@ -751,20 +763,29 @@ postfix = i:value ( DOT s:IDENT a:argumentList { i = newInvoke( |
|
|
|
) * { $$ = i } |
|
|
|
|
|
|
|
paramList = LPAREN m:makeMap |
|
|
|
( i:IDENT { map_append(m, i) } |
|
|
|
( COMMA i:IDENT { map_append(m, i) } |
|
|
|
( p:parameter { map_append(m, p) } |
|
|
|
( COMMA p:parameter { map_append(m, p) } |
|
|
|
) * |
|
|
|
) ? |
|
|
|
RPAREN { $$ = m } |
|
|
|
|
|
|
|
parameter = ATAT p:value { $$ = newUnary(Unsplice_proto, p) } |
|
|
|
| p:ident { $$ = p } |
|
|
|
|
|
|
|
argumentList = LPAREN m:makeMap |
|
|
|
( e:exp { map_append(m, e) } |
|
|
|
( COMMA e:exp { map_append(m, e) } |
|
|
|
( a:argument { map_append(m, a) } |
|
|
|
( COMMA a:argument { map_append(m, a) } |
|
|
|
) * |
|
|
|
) ? |
|
|
|
RPAREN { $$ = m } |
|
|
|
|
|
|
|
value = n:FLOAT { $$ = newFloat(n) } |
|
|
|
argument = ATAT e:value { $$ = newUnary(Unsplice_proto, e) } |
|
|
|
| MULTI e:exp { $$ = newUnary(Splice_proto, e) } |
|
|
|
| e:exp { $$ = e } |
|
|
|
|
|
|
|
value = BACKTICK n:value { $$ = newUnary(Quasiquote_proto, n) } |
|
|
|
| AT n:value { $$ = newUnary(Unquote_proto, n) } |
|
|
|
| n:FLOAT { $$ = newFloat(n) } |
|
|
|
| n:integer { $$ = newInteger(n) } |
|
|
|
| s:string { $$ = newString(s) } |
|
|
|
| s:symbol { $$ = s } |
|
|
@ -790,11 +811,11 @@ map = LCB m:makeMap |
|
|
|
) ? |
|
|
|
RCB { $$ = m } |
|
|
|
| LBRAC m:makeMap |
|
|
|
( v:exp { map_append(m, v) } |
|
|
|
( COMMA v:exp { map_append(m, v) } |
|
|
|
( v:argument { map_append(m, v) } |
|
|
|
( COMMA v:argument { map_append(m, v) } |
|
|
|
) * |
|
|
|
) ? |
|
|
|
RBRAC { $$ = m } |
|
|
|
RBRAC { $$ = m } |
|
|
|
|
|
|
|
makeMap = { $$ = makeMap() } |
|
|
|
|
|
|
@ -891,7 +912,8 @@ SEMICOLON = ';' - |
|
|
|
COMMA = ',' - |
|
|
|
DOT = '.' - |
|
|
|
BACKTICK= '`' - |
|
|
|
AT = '@' - |
|
|
|
AT = '@' ![@] - |
|
|
|
ATAT = '@@' ![@] - |
|
|
|
LCB = '{' - |
|
|
|
RCB = '}' - |
|
|
|
LBRAC = '[' - |
|
|
@ -939,6 +961,11 @@ oop clone(oop obj) |
|
|
|
set(map, Map, elements, elements); |
|
|
|
return map; |
|
|
|
} |
|
|
|
case Function: { |
|
|
|
oop fun= malloc(sizeof(*obj)); |
|
|
|
memcpy(fun, obj, sizeof(*obj)); |
|
|
|
return fun; |
|
|
|
} |
|
|
|
} |
|
|
|
return obj; |
|
|
|
} |
|
|
@ -1087,22 +1114,52 @@ oop modOperation(oop lhs, oop rhs) |
|
|
|
#undef TYPESIG |
|
|
|
#undef CASE |
|
|
|
|
|
|
|
oop expandUnquotes(oop scope, oop obj) |
|
|
|
{ |
|
|
|
obj = clone(obj); |
|
|
|
if (!is(Map, obj)) { |
|
|
|
return obj; |
|
|
|
} |
|
|
|
if (map_get(obj, __proto___symbol) == Unquote_proto) { |
|
|
|
return eval(scope, map_get(obj, rhs_symbol)); |
|
|
|
} |
|
|
|
for (size_t i= 0; i < map_size(obj); ++i) { |
|
|
|
struct Pair *pair= &get(obj, Map, elements)[i]; |
|
|
|
if (__proto___symbol != pair->key) { |
|
|
|
pair->value= expandUnquotes(scope, pair->value); |
|
|
|
} |
|
|
|
oop expandUnquotes(oop scope, oop ast) |
|
|
|
{ |
|
|
|
if (!is(Map, ast)) return clone(ast); |
|
|
|
|
|
|
|
if (Unquote_proto == map_get(ast, __proto___symbol)) return eval(scope, map_get(ast, rhs_symbol)); |
|
|
|
if (Unsplice_proto == map_get(ast, __proto___symbol)) runtimeError("@@ outside of array expression"); |
|
|
|
|
|
|
|
oop map= makeMap(); |
|
|
|
if (map_isArray(ast)) { |
|
|
|
for (size_t i= 0; i < map_size(ast); ++i) { |
|
|
|
struct Pair *pair= &get(ast, Map, elements)[i]; |
|
|
|
if (!is(Map, pair->value)) { |
|
|
|
map_append(map, clone(pair->value)); |
|
|
|
continue; |
|
|
|
} |
|
|
|
oop proto= map_get(pair->value, __proto___symbol); |
|
|
|
if (Unquote_proto == proto) { |
|
|
|
map_append(map, eval(scope, map_get(pair->value, rhs_symbol))); |
|
|
|
continue; |
|
|
|
} |
|
|
|
if (Unsplice_proto == proto) { |
|
|
|
oop sub= eval(scope, map_get(pair->value, rhs_symbol)); |
|
|
|
if (is(Map, sub) && (Map_proto == map_get(sub, __proto___symbol))) sub= map_get(sub, value_symbol); |
|
|
|
if (!map_isArray(sub)) runtimeError("cannot splice non-array: %s", printString(sub)); |
|
|
|
for (size_t j= 0; j < map_size(sub); ++j) |
|
|
|
map_append(map, get(sub, Map, elements)[j].value); |
|
|
|
continue; |
|
|
|
} |
|
|
|
map_append(map, expandUnquotes(scope, pair->value)); |
|
|
|
} |
|
|
|
} |
|
|
|
else { |
|
|
|
for (size_t i= 0; i < map_size(ast); ++i) { |
|
|
|
struct Pair *pair= &get(ast, Map, elements)[i]; |
|
|
|
oop key= expandUnquotes(scope, pair->key); |
|
|
|
if (!is(Map, pair->value)) { |
|
|
|
map_set(map, key, clone(pair->value)); |
|
|
|
continue; |
|
|
|
} |
|
|
|
if (__proto___symbol == key) |
|
|
|
map_set(map, key, pair->value); |
|
|
|
else |
|
|
|
map_set(map, key, expandUnquotes(scope, pair->value)); |
|
|
|
} |
|
|
|
} |
|
|
|
return obj; |
|
|
|
return map; |
|
|
|
} |
|
|
|
|
|
|
|
oop applyOperator(oop op, oop lhs, oop rhs) |
|
|
@ -1260,6 +1317,9 @@ oop eval(oop scope, oop ast) |
|
|
|
case t_Unquote: { |
|
|
|
runtimeError("@ outside of `"); |
|
|
|
} |
|
|
|
case t_Unsplice: { |
|
|
|
runtimeError("@@ outside of `"); |
|
|
|
} |
|
|
|
case t_Declaration: { |
|
|
|
oop lhs = map_get(ast, lhs_symbol); |
|
|
|
oop rhs = eval(scope, map_get(ast, rhs_symbol)); |
|
|
@ -1506,6 +1566,9 @@ oop eval(oop scope, oop ast) |
|
|
|
} |
|
|
|
return apply(scope, this, func, args, ast); |
|
|
|
} |
|
|
|
case t_Splice: { |
|
|
|
runtimeError("* outside of argument list"); |
|
|
|
} |
|
|
|
|
|
|
|
case t_Return: { |
|
|
|
assert(jbs); |
|
|
@ -1608,12 +1671,24 @@ oop eval(oop scope, oop ast) |
|
|
|
oop key = eval(scope, map_get(ast, key_symbol)); |
|
|
|
switch (getType(map)) { |
|
|
|
case String: |
|
|
|
if (getInteger(key) >= get(map, String, size)) { |
|
|
|
runtimeError("GetIndex out of range on String"); |
|
|
|
if (!isInteger(key)) { |
|
|
|
runtimeError("non-integer index"); |
|
|
|
} |
|
|
|
return makeInteger(unescape(get(map, String, value))[getInteger(key)]); |
|
|
|
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"); |
|
|
|
} |
|
|
|
return makeInteger(get(map, String, value)[i]); |
|
|
|
case Map: |
|
|
|
return getVariable(map, key); |
|
|
|
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); |
|
|
|
default: |
|
|
|
runtimeError("GetIndex on non Map or String"); |
|
|
|
} |
|
|
@ -1626,7 +1701,7 @@ oop eval(oop scope, oop ast) |
|
|
|
switch (getType(map)) { |
|
|
|
case String: |
|
|
|
if (getInteger(key) >= get(map, String, size)) { |
|
|
|
runtimeError("SetIndex out of range on String"); |
|
|
|
runtimeError("SetIndex out of bounds on String"); |
|
|
|
} |
|
|
|
get(map, String, value)[getInteger(key)] = getInteger(value); |
|
|
|
return value; |
|
|
@ -1638,6 +1713,35 @@ 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_Integer: |
|
|
|
case t_Float: |
|
|
@ -1819,11 +1923,29 @@ oop prim_keys(oop scope, oop params) |
|
|
|
return null; |
|
|
|
} |
|
|
|
|
|
|
|
oop prim_allKeys(oop scope, oop params) |
|
|
|
{ |
|
|
|
if (map_hasIntegerKey(params, 0)) { |
|
|
|
oop arg= get(params, Map, elements)[0].value; |
|
|
|
if (is(Map, arg)) return map_allKeys(arg); |
|
|
|
} |
|
|
|
return null; |
|
|
|
} |
|
|
|
|
|
|
|
oop prim_values(oop scope, oop params) |
|
|
|
{ |
|
|
|
if (map_hasIntegerKey(params, 0)) { |
|
|
|
oop arg= get(params, Map, elements)[0].value; |
|
|
|
if (is(Map, arg)) return map_values(arg); |
|
|
|
oop arg= get(params, Map, elements)[0].value; |
|
|
|
if (is(Map, arg)) return map_values(arg); |
|
|
|
} |
|
|
|
return null; |
|
|
|
} |
|
|
|
|
|
|
|
oop prim_allValues(oop scope, oop params) |
|
|
|
{ |
|
|
|
if (map_hasIntegerKey(params, 0)) { |
|
|
|
oop arg= get(params, Map, elements)[0].value; |
|
|
|
if (is(Map, arg)) return map_allValues(arg); |
|
|
|
} |
|
|
|
return null; |
|
|
|
} |
|
|
@ -1871,16 +1993,27 @@ oop prim_print(oop scope, oop params) |
|
|
|
return params; |
|
|
|
} |
|
|
|
|
|
|
|
oop evalArgs(oop scope, oop args) |
|
|
|
oop evalArgs(oop scope, oop asts) |
|
|
|
{ |
|
|
|
int i = 0; |
|
|
|
oop params = makeMap(); |
|
|
|
oop index; |
|
|
|
while ((index = makeInteger(i)), map_hasKey(args, index)) { |
|
|
|
map_set(params, index, eval(scope, map_get(args, index))); |
|
|
|
i++; |
|
|
|
} |
|
|
|
return params; |
|
|
|
oop args= makeMap(); |
|
|
|
size_t nargs= map_size(asts); |
|
|
|
for (size_t i= 0; i < nargs; ++i) { |
|
|
|
oop ast= get(asts, Map, elements)[i].value; |
|
|
|
if (is(Map, ast) && (Splice_proto == map_get(ast, __proto___symbol))) { |
|
|
|
oop splice= eval(scope, map_get(ast, rhs_symbol)); |
|
|
|
if (!is(Map, splice)) map_append(args, splice); |
|
|
|
else { |
|
|
|
size_t nsplice= map_size(splice); |
|
|
|
for (size_t j= 0; j < nsplice; ++j) { |
|
|
|
map_append(args, get(splice, Map, elements)[j].value); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
else { |
|
|
|
map_append(args, eval(scope, ast)); |
|
|
|
} |
|
|
|
} |
|
|
|
return args; |
|
|
|
} |
|
|
|
|
|
|
|
oop AST= NULL; |
|
|
@ -1940,8 +2073,218 @@ oop prim_import(oop scope, oop params) |
|
|
|
|
|
|
|
oop prim_String(oop scope, oop params) |
|
|
|
{ |
|
|
|
if (!map_hasIntegerKey(params, 0)) return null; |
|
|
|
return makeString(printString(get(params, Map, elements)[0].value)); |
|
|
|
if (!map_hasIntegerKey(params, 0)) return makeString(""); |
|
|
|
oop arg= get(params, Map, elements)[0].value; |
|
|
|
switch (getType(arg)) { |
|
|
|
case Undefined: { |
|
|
|
return makeString(""); |
|
|
|
} |
|
|
|
case Integer: { |
|
|
|
int repeat= getInteger(arg); |
|
|
|
if (!map_hasIntegerKey(params, 1)) { |
|
|
|
return makeStringFromChar('\0', repeat); |
|
|
|
} |
|
|
|
char c= getInteger(get(params, Map, elements)[1].value); |
|
|
|
return makeStringFromChar(c, repeat); |
|
|
|
} |
|
|
|
case String: { |
|
|
|
return clone(arg); |
|
|
|
} |
|
|
|
case Map: { |
|
|
|
if (map_isArray(arg)) { |
|
|
|
size_t len= map_size(arg); |
|
|
|
char *str= malloc(sizeof(char) * len + 1); |
|
|
|
for (size_t i=0; i < len; ++i) { |
|
|
|
str[i]= getInteger(get(arg, Map, elements)[i].value); |
|
|
|
} |
|
|
|
return makeStringFrom(str, len); |
|
|
|
} |
|
|
|
} |
|
|
|
case Symbol: { |
|
|
|
return makeString(get(arg, Symbol, name)); |
|
|
|
} |
|
|
|
} |
|
|
|
runtimeError("cannot make string from: %s", printString(arg)); |
|
|
|
return NULL; |
|
|
|
} |
|
|
|
|
|
|
|
oop prim_Symbol(oop scope, oop params) |
|
|
|
{ |
|
|
|
oop arg= null; |
|
|
|
if (map_hasIntegerKey(params, 0)) { |
|
|
|
arg= get(params, Map, elements)[0].value; |
|
|
|
switch (getType(arg)) { |
|
|
|
case Integer: { |
|
|
|
if (map_hasIntegerKey(params, 1)) { |
|
|
|
int repeat= getInteger(arg); |
|
|
|
char c= getInteger(get(params, Map, elements)[1].value); |
|
|
|
return makeSymbolFromChar(c, repeat); |
|
|
|
} |
|
|
|
break; |
|
|
|
} |
|
|
|
case String: { |
|
|
|
return makeSymbol(get(arg, String, value)); |
|
|
|
} |
|
|
|
case Map: { |
|
|
|
if (map_isArray(arg)) { |
|
|
|
size_t len= map_size(arg); |
|
|
|
char *str= malloc(sizeof(char) * len + 1); |
|
|
|
for (size_t i=0; i < len; ++i) { |
|
|
|
str[i]= getInteger(get(arg, Map, elements)[i].value); |
|
|
|
} |
|
|
|
return makeSymbolFrom(str); |
|
|
|
} |
|
|
|
} |
|
|
|
case Symbol: { |
|
|
|
return arg; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
runtimeError("cannot make symbol from: %s", printString(arg)); |
|
|
|
return NULL; |
|
|
|
} |
|
|
|
|
|
|
|
oop prim_Integer(oop scope, oop params) |
|
|
|
{ |
|
|
|
oop arg= null; |
|
|
|
if (map_hasIntegerKey(params, 0)) { |
|
|
|
arg= get(params, Map, elements)[0].value; |
|
|
|
switch (getType(arg)) { |
|
|
|
case Undefined: { |
|
|
|
return makeInteger(0); |
|
|
|
} |
|
|
|
case Integer: { |
|
|
|
return arg; |
|
|
|
} |
|
|
|
case String: { |
|
|
|
if (!map_hasIntegerKey(params, 1)) { |
|
|
|
return makeInteger(strtoll(get(arg, String, value), NULL, 0)); |
|
|
|
} |
|
|
|
int base= getInteger(get(params, Map, elements)[1].value); |
|
|
|
if (base > 36 || base < 2) { |
|
|
|
runtimeError("base must be between 2 and 36 inclusive"); |
|
|
|
} |
|
|
|
return makeInteger(strtoll(get(arg, String, value), NULL, base)); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
runtimeError("cannot make integer from: %s", printString(arg)); |
|
|
|
return NULL; |
|
|
|
} |
|
|
|
|
|
|
|
oop prim_Map(oop scope, oop params) |
|
|
|
{ |
|
|
|
if (!map_hasIntegerKey(params, 0)) return makeMap(); |
|
|
|
oop arg= get(params, Map, elements)[0].value; |
|
|
|
switch (getType(arg)) { |
|
|
|
case Undefined: { |
|
|
|
return makeMap(); |
|
|
|
} |
|
|
|
case Integer: { |
|
|
|
return makeMapCapacity(getInteger(arg)); |
|
|
|
} |
|
|
|
case Map: { |
|
|
|
return clone(arg); |
|
|
|
} |
|
|
|
} |
|
|
|
runtimeError("cannot make map from: %s", printString(arg)); |
|
|
|
return NULL; |
|
|
|
} |
|
|
|
|
|
|
|
oop prim_Array(oop scope, oop params) |
|
|
|
{ |
|
|
|
if (!map_hasIntegerKey(params, 0)) return makeMap(); |
|
|
|
oop arg= get(params, Map, elements)[0].value; |
|
|
|
switch (getType(arg)) { |
|
|
|
case Undefined: { |
|
|
|
return makeMap(); |
|
|
|
} |
|
|
|
case Integer: { |
|
|
|
int repeat= getInteger(arg); |
|
|
|
oop array= NULL; |
|
|
|
if (map_hasIntegerKey(params, 1)) { |
|
|
|
array= makeArrayFromElement(get(params, Map, elements)[1].value, repeat); |
|
|
|
} else { |
|
|
|
array= makeArrayFromElement(null, repeat); |
|
|
|
} |
|
|
|
return array; |
|
|
|
} |
|
|
|
case Symbol: { |
|
|
|
return makeArrayFromString(get(arg, Symbol, name)); |
|
|
|
} |
|
|
|
case String: { |
|
|
|
return makeArrayFromString(get(arg, String, value)); |
|
|
|
} |
|
|
|
case Map: { |
|
|
|
return clone(arg); |
|
|
|
} |
|
|
|
} |
|
|
|
runtimeError("cannot make array from: %s", printString(arg)); |
|
|
|
return NULL; |
|
|
|
} |
|
|
|
|
|
|
|
oop prim_Function(oop scope, oop params) |
|
|
|
{ |
|
|
|
oop arg= null; |
|
|
|
if (map_hasIntegerKey(params, 0)) { |
|
|
|
arg= get(params, Map, elements)[0].value; |
|
|
|
switch (getType(arg)) { |
|
|
|
case Function: { |
|
|
|
if (isTrue(get(arg, Function, fixed))) { |
|
|
|
oop unfix= clone(arg); |
|
|
|
set(unfix, Function, fixed, makeInteger(0)); |
|
|
|
return unfix; |
|
|
|
} else { |
|
|
|
return clone(arg); |
|
|
|
} |
|
|
|
} |
|
|
|
case Map: { |
|
|
|
if (map_hasIntegerKey(params, 1) && map_hasIntegerKey(params, 2) && map_hasIntegerKey(params, 3)) { |
|
|
|
oop param= arg; |
|
|
|
oop body= get(params, Map, elements)[1].value; |
|
|
|
oop parentScope= get(params, Map, elements)[2].value; |
|
|
|
oop name= get(params, Map, elements)[3].value; |
|
|
|
if (is(Map, body) && is(Map, parentScope) && is(Map, name)) { |
|
|
|
return makeFunction(NULL, name, param, body, parentScope, makeInteger(0)); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
runtimeError("cannot make function from: %s", printString(arg)); |
|
|
|
return NULL; |
|
|
|
} |
|
|
|
|
|
|
|
oop prim_Syntax(oop scope, oop params) |
|
|
|
{ |
|
|
|
oop arg= null; |
|
|
|
if (map_hasIntegerKey(params, 0)) { |
|
|
|
arg= get(params, Map, elements)[0].value; |
|
|
|
switch (getType(arg)) { |
|
|
|
case Function: { |
|
|
|
if (isFalse(get(arg, Function, fixed))) { |
|
|
|
oop fix= clone(arg); |
|
|
|
set(fix, Function, fixed, makeInteger(1)); |
|
|
|
return fix; |
|
|
|
} else { |
|
|
|
return clone(arg); |
|
|
|
} |
|
|
|
} |
|
|
|
case Map: { |
|
|
|
if (map_hasIntegerKey(params, 1) && map_hasIntegerKey(params, 2) && map_hasIntegerKey(params, 3)) { |
|
|
|
oop param= arg; |
|
|
|
oop body= get(params, Map, elements)[1].value; |
|
|
|
oop parentScope= get(params, Map, elements)[2].value; |
|
|
|
oop name= get(params, Map, elements)[3].value; |
|
|
|
if (is(Map, body) && is(Map, parentScope) && is(Map, name)) { |
|
|
|
return makeFunction(NULL, name, param, body, parentScope, makeInteger(1)); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
runtimeError("cannot make syntax from: %s", printString(arg)); |
|
|
|
return NULL; |
|
|
|
} |
|
|
|
|
|
|
|
oop prim_scope(oop scope, oop params) |
|
|
@ -1969,7 +2312,9 @@ int main(int argc, char **argv) |
|
|
|
|
|
|
|
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("allKeys" ), makeFunction(prim_allKeys, intern("allKeys" ), null, null, globals, null)); |
|
|
|
map_set(globals, intern("values" ), makeFunction(prim_values, intern("values" ), null, null, globals, null)); |
|
|
|
map_set(globals, intern("allValues" ), makeFunction(prim_allValues, intern("allValues" ), 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)); |
|
|
@ -1978,6 +2323,12 @@ int main(int argc, char **argv) |
|
|
|
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("String" ), makeFunction(prim_String , intern("String" ), null, null, globals, null)); |
|
|
|
map_set(globals, intern("Integer" ), makeFunction(prim_Integer , intern("Integer" ), null, null, globals, null)); |
|
|
|
map_set(globals, intern("Symbol" ), makeFunction(prim_Symbol , intern("Symbol" ), null, null, globals, null)); |
|
|
|
map_set(globals, intern("Map" ), makeFunction(prim_Map , intern("Map" ), null, null, globals, null)); |
|
|
|
map_set(globals, intern("Array" ), makeFunction(prim_Array , intern("Array" ), null, null, globals, null)); |
|
|
|
map_set(globals, intern("Function" ), makeFunction(prim_Function , intern("Function" ), null, null, globals, null)); |
|
|
|
map_set(globals, intern("Syntax" ), makeFunction(prim_Syntax , intern("Syntax" ), null, null, globals, null)); |
|
|
|
|
|
|
|
map_set(globals, intern("scope"), makeFunction(prim_scope, intern("scope"), null, null, globals, null)); |
|
|
|
|
|
|
|