Преглед на файлове

add allKeys, allValues; add @@ syntax to unquote and splice an array into a list of arguments or parameters

master
Ian Piumarta преди 4 години
родител
ревизия
f070bc84c4
променени са 4 файла, в които са добавени 111 реда и са изтрити 37 реда
  1. +1
    -1
      bootstrap.txt
  2. +15
    -0
      object.c
  3. +92
    -31
      parse.leg
  4. +3
    -5
      test-object.txt

+ 1
- 1
bootstrap.txt Целия файл

@ -4,7 +4,7 @@ fun require(__fileName__) {
if (__requires__[__fileName__] != null) {
return __requires__[__fileName__]
}
import(__fileName__);
import(__fileName__);
__requires__[__fileName__]= scope();
return scope();
}

+ 15
- 0
object.c Целия файл

@ -323,6 +323,11 @@ bool map_hasIntegerKey(oop map, size_t index)
return index == getInteger(key);
}
int map_isArray(oop map)
{
return map_hasIntegerKey(map, 0) && map_hasIntegerKey(map, map_size(map) - 1);
}
int oopcmp(oop a, oop b)
{
type_t ta = getType(a), tb = getType(b);
@ -498,6 +503,16 @@ oop map_values(oop map)
return values;
}
oop map_allValues(oop map)
{
assert(is(Map, map));
oop values = makeMap();
for (size_t i = 0; i < get(map, Map, size); i++) {
map_append(values, get(map, Map, elements)[i].value);
}
return values;
}
DECLARE_BUFFER(oop, OopStack);
OopStack printing = BUFFER_INITIALISER;

+ 92
- 31
parse.leg Целия файл

@ -21,7 +21,7 @@
_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) _DO(Unsplice)
typedef enum {
t_UNDEFINED=0,
@ -642,7 +642,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)) }
@ -730,8 +730,6 @@ 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) }
@ -743,20 +741,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) }
| AT p:value { $$ = newUnary(Unquote_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:NUMBER { $$ = newInteger(n) }
argument = ATAT a:value { $$ = newUnary(Unsplice_proto, a) }
| a:exp { $$ = a }
value = BACKTICK n:value { $$ = newUnary(Quasiquote_proto, n) }
| AT n:value { $$ = newUnary(Unquote_proto, n) }
| n:NUMBER { $$ = newInteger(n) }
| s:string { $$ = newString(s) }
| s:symbol { $$ = s }
| m:map { $$ = newMap(m) }
@ -781,15 +788,15 @@ 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() }
key = IDENT | NUMBER
key = ident | NUMBER
- = (blank | comment)*
@ -874,7 +881,8 @@ SEMICOLON = ';' -
COMMA = ',' -
DOT = '.' -
BACKTICK= '`' -
AT = '@' -
AT = '@' ![@] -
ATAT = '@@' ![@] -
LCB = '{' -
RCB = '}' -
LBRAC = '[' -
@ -1039,22 +1047,52 @@ oop mulOperation(oop ast, 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 ast, oop op, oop lhs, oop rhs)
@ -1211,6 +1249,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));
@ -1772,11 +1813,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;
}
@ -1922,7 +1981,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));

+ 3
- 5
test-object.txt Целия файл

@ -81,18 +81,16 @@ syntax double(a) {
return `(@a+@a)
}
double(21)
println(double(21))
syntax until(c, b) {
syntax until (c) b {
return `(while (!@c) @b)
}
var x = 0;
/*
until(x==10) {
until (x==10) {
println(x++)
}
*/
println(`x);

Зареждане…
Отказ
Запис