diff options
author | ubq323 <ubq323@ubq323.website> | 2024-06-26 22:45:16 +0100 |
---|---|---|
committer | ubq323 <ubq323@ubq323.website> | 2024-06-26 22:45:16 +0100 |
commit | a559125a2d7af771784614b7a2092cc7fb707345 (patch) | |
tree | 4e4f31197d28a41b5c62fdd19086295cf0acad84 | |
parent | 2e62b41072738142dea9f0b5dd5d2d22455c7616 (diff) |
array literals
-rw-r--r-- | ast.c | 18 | ||||
-rw-r--r-- | ast.h | 2 | ||||
-rw-r--r-- | com.c | 12 | ||||
-rw-r--r-- | dis.c | 2 | ||||
-rw-r--r-- | g.peg | 6 | ||||
-rw-r--r-- | tests/arr2.bth | 1 | ||||
-rw-r--r-- | tests/arr2.out | 1 | ||||
-rw-r--r-- | tests/arr3.bth | 1 | ||||
-rw-r--r-- | tests/arr3.out | 1 | ||||
-rw-r--r-- | tests/arr4.bth | 4 | ||||
-rw-r--r-- | tests/arr4.out | 1 | ||||
-rw-r--r-- | tests/arr5.bth | 3 | ||||
-rw-r--r-- | tests/arr5.out | 1 | ||||
-rw-r--r-- | todo | 5 | ||||
-rw-r--r-- | vm.c | 15 | ||||
-rw-r--r-- | vm.h | 3 |
16 files changed, 71 insertions, 5 deletions
@@ -27,7 +27,7 @@ void astvec_append(AstVec *v, AstNode val) { void astnode_append(AstNode *l, AstNode val) { // printf(" astnode_append: %d\n",l->ty); - assert(l->ty == AST_LIST); + assert(l->ty == AST_LIST || l->ty == AST_ARR); astvec_append(&l->as.list, val); } @@ -48,6 +48,14 @@ AstNode astnode_new_list() { } }; } +AstNode astnode_new_arr() { + return (AstNode){ + .ty = AST_ARR, + .as = { + .list = astvec_new() + } + }; +} AstNode astnode_new_ident(const char *s) { return (AstNode){ @@ -74,7 +82,8 @@ void astnode_free(AstNode *a) { case AST_STRING: free(a->as.str); break; - case AST_LIST:; + case AST_LIST: + case AST_ARR:; AstVec *v = &a->as.list; for (int i = 0; i < v->len; i++) { astnode_free(&v->vals[i]); @@ -92,7 +101,8 @@ void astnode_disp(AstNode *a) { case AST_NUM: printf("%s:%d ",ast_ty_to_str(a->ty),a->as.num); break; - case AST_LIST:; + case AST_LIST: + case AST_ARR:; AstVec *v = &a->as.list; printf("%s:(",ast_ty_to_str(a->ty)); for (int i = 0; i < v->len; i++) { @@ -109,7 +119,7 @@ void astnode_disp(AstNode *a) { } const char* ty_names[] = { - "list", "num", "ident", "string" + "list", "num", "ident", "string", "arr", }; const char *ast_ty_to_str(AstTy ty) { return ty_names[ty]; @@ -9,6 +9,7 @@ typedef enum { AST_NUM, AST_IDENT, AST_STRING, + AST_ARR, } AstTy; struct _astnode; @@ -36,6 +37,7 @@ void astnode_append(AstNode *l, AstNode val); AstNode astnode_new_num(int n); AstNode astnode_new_list(); +AstNode astnode_new_arr(); AstNode astnode_new_ident(const char *s); AstNode astnode_new_string(const char *s); @@ -38,6 +38,7 @@ static int stack_effect_of(Op opcode) { case OP_NIL: case OP_TRUE: case OP_FALSE: + case OP_ARRNEW: return 1; case OP_SKIP: case OP_REDO: @@ -55,6 +56,7 @@ static int stack_effect_of(Op opcode) { case OP_CMP: case OP_EQU: case OP_MOD: + case OP_ARRAPPEND: return -1; // these ones depend on their argument. handle them specifically @@ -402,6 +404,16 @@ static void compile_node(Compiler *C, AstNode a) { compile_byte(C, compile_constant(C, VAL_OBJ(o))); break; } + case AST_ARR: { + compile_opcode(C, OP_ARRNEW); + AstVec v = a.as.list; + for (int i = 0; i < v.len; i++) { + compile_node(C, v.vals[i]); + compile_opcode(C, OP_ARRAPPEND); + } + break; + } + case AST_LIST: { AstVec l = a.as.list; @@ -101,6 +101,8 @@ static size_t disasm_instr_h(Chunk *ch, size_t ip, int depth) { SIMPLE_INSTR(OP_CMP, "cmp") SIMPLE_INSTR(OP_EQU, "equ") SIMPLE_INSTR(OP_HALT, "halt") + SIMPLE_INSTR(OP_ARRNEW, "arrnew") + SIMPLE_INSTR(OP_ARRAPPEND, "arrappend") #undef SIMPLE_INSTR default: @@ -29,12 +29,18 @@ expr <- / n:number { $$ = n; } / i:ident { $$ = i; } / t:string { $$ = t; } + / a:array { $$ = a; } list <- { $$ = astnode_new_list(); } '(' ( e:expr { astnode_append(&$$, e); } )* ')' _ +array <- { $$ = astnode_new_arr(); } + '[' + ( e:expr { astnode_append(&$$, e); } + )* + ']' _ number <- < [0-9]+ > (! ident_char) _ { $$ = astnode_new_num(atoi($1)); } ident <- < ident_char+ > _ { $$ = astnode_new_ident($1); } diff --git a/tests/arr2.bth b/tests/arr2.bth new file mode 100644 index 0000000..a405bde --- /dev/null +++ b/tests/arr2.bth @@ -0,0 +1 @@ +(say (append [1 2 3 4] 99)) diff --git a/tests/arr2.out b/tests/arr2.out new file mode 100644 index 0000000..42a9264 --- /dev/null +++ b/tests/arr2.out @@ -0,0 +1 @@ +[ 1 2 3 4 99 ] diff --git a/tests/arr3.bth b/tests/arr3.bth new file mode 100644 index 0000000..c2bce88 --- /dev/null +++ b/tests/arr3.bth @@ -0,0 +1 @@ +(say (append [1 2 (+ 1 2) (let (x 2) (* x x))] (+ 2 3))) diff --git a/tests/arr3.out b/tests/arr3.out new file mode 100644 index 0000000..f5d7903 --- /dev/null +++ b/tests/arr3.out @@ -0,0 +1 @@ +[ 1 2 3 4 5 ] diff --git a/tests/arr4.bth b/tests/arr4.bth new file mode 100644 index 0000000..2521e63 --- /dev/null +++ b/tests/arr4.bth @@ -0,0 +1,4 @@ +(say + (let (A (append [1 2 3 (let (x 2) (* x x)) 5] 6)) + (let (B (append A 7)) (append B 8)) + (append (append A 9) 10))) diff --git a/tests/arr4.out b/tests/arr4.out new file mode 100644 index 0000000..c508125 --- /dev/null +++ b/tests/arr4.out @@ -0,0 +1 @@ +[ 1 2 3 4 5 6 7 8 9 10 ] diff --git a/tests/arr5.bth b/tests/arr5.bth new file mode 100644 index 0000000..79d5a7d --- /dev/null +++ b/tests/arr5.bth @@ -0,0 +1,3 @@ +(set A [1 2 3]) +(let (B A) (append B 10)) +(say A) diff --git a/tests/arr5.out b/tests/arr5.out new file mode 100644 index 0000000..7704f22 --- /dev/null +++ b/tests/arr5.out @@ -0,0 +1 @@ +[ 1 2 3 10 ] @@ -1,5 +1,8 @@ closures, upvalues -lists, hashes, other useful types +arrays, hashes, other useful types +good loops +declarations inline +pattern matching garbage collector macros @@ -233,8 +233,23 @@ int runvm(State *S) { goto done; break; + case OP_ARRNEW: { + ObjArr *a = objarr_new(S); + PUSH(VAL_OBJ(a)); + break; + } + case OP_ARRAPPEND: { + Val v = POP(); + Val a = PEEK(); + CHECK(IS_ARR(a), "can only append to array"); + ObjArr *arr = AS_ARR(a); + objarr_append(S, arr, v); + break; } + } + + } done:; return status; @@ -62,6 +62,9 @@ typedef enum { OP_CALL, OP_ENDSCOPE, + + OP_ARRNEW, + OP_ARRAPPEND, } Op; int runvm(State *S); |