summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ast.c18
-rw-r--r--ast.h2
-rw-r--r--com.c12
-rw-r--r--dis.c2
-rw-r--r--g.peg6
-rw-r--r--tests/arr2.bth1
-rw-r--r--tests/arr2.out1
-rw-r--r--tests/arr3.bth1
-rw-r--r--tests/arr3.out1
-rw-r--r--tests/arr4.bth4
-rw-r--r--tests/arr4.out1
-rw-r--r--tests/arr5.bth3
-rw-r--r--tests/arr5.out1
-rw-r--r--todo5
-rw-r--r--vm.c15
-rw-r--r--vm.h3
16 files changed, 71 insertions, 5 deletions
diff --git a/ast.c b/ast.c
index b6fcbcf..4fbd471 100644
--- a/ast.c
+++ b/ast.c
@@ -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];
diff --git a/ast.h b/ast.h
index ead9cc6..6896c2b 100644
--- a/ast.h
+++ b/ast.h
@@ -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);
diff --git a/com.c b/com.c
index 0ae79f6..695802a 100644
--- a/com.c
+++ b/com.c
@@ -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;
diff --git a/dis.c b/dis.c
index 9220b75..2939384 100644
--- a/dis.c
+++ b/dis.c
@@ -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:
diff --git a/g.peg b/g.peg
index dccf361..056ca7a 100644
--- a/g.peg
+++ b/g.peg
@@ -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 ]
diff --git a/todo b/todo
index f724c3a..d9d819e 100644
--- a/todo
+++ b/todo
@@ -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
diff --git a/vm.c b/vm.c
index 679a6a5..023d2c3 100644
--- a/vm.c
+++ b/vm.c
@@ -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;
diff --git a/vm.h b/vm.h
index 4af6300..8479623 100644
--- a/vm.h
+++ b/vm.h
@@ -62,6 +62,9 @@ typedef enum {
OP_CALL,
OP_ENDSCOPE,
+
+ OP_ARRNEW,
+ OP_ARRAPPEND,
} Op;
int runvm(State *S);