diff --git a/src/compiler.c b/src/compiler.c index 5a71b59..59c1ea8 100644 --- a/src/compiler.c +++ b/src/compiler.c @@ -64,6 +64,11 @@ void compile_node(compiler* self, node* root, program* prog) compile_children(self, root, prog); program_add_instr(prog, OP_CAT, NO_PARAM); } + else if (lhs == rhs && lhs == TY_ARRAY) + { + compile_children(self, root, prog); + program_add_instr(prog, OP_ACAT, NO_PARAM); + } else { compile_number(self, root, prog, OP_IADD, OP_FADD); diff --git a/src/cstatic.c b/src/cstatic.c index fc34ad7..73b21a1 100644 --- a/src/cstatic.c +++ b/src/cstatic.c @@ -70,15 +70,7 @@ type* cstatic_resolve_new(cstatic* self, node* ast) else if (ast->type == NODE_ADD) { - int lhs = cstatic_resolve_base_type(self, ast->children.data[0]); - int rhs = cstatic_resolve_base_type(self, ast->children.data[1]); - - if (lhs == TY_STRING && rhs == TY_STRING) - { - return cstatic_new_type(self, TY_STRING); - } - - return cstatic_new_type(self, lhs); + return cstatic_resolve_new(self, ast->children.data[0]); } else if (ast->type == NODE_STRING) @@ -213,6 +205,24 @@ int cstatic_check(cstatic* self, node* ast, char* msg, size_t size) return 1; } + + // Array Operations + if (ast->type == NODE_ADD) + { + type* lhs = cstatic_resolve_new(self, ast->children.data[0]); + type* rhs = cstatic_resolve_new(self, ast->children.data[1]); + + if (lhs->base_type == TY_ARRAY + && type_equals(lhs, rhs)) + { + type_free(lhs); free(lhs); + type_free(rhs); free(rhs); + return 1; + } + + type_free(lhs); free(lhs); + type_free(rhs); free(rhs); + } // String Operations if (ast->type == NODE_ADD) diff --git a/src/opcodes.h b/src/opcodes.h index 848d375..9d4c289 100644 --- a/src/opcodes.h +++ b/src/opcodes.h @@ -29,7 +29,8 @@ G(OP_CAT), \ G(OP_SMUL), \ G(OP_MKARRAY), \ - G(OP_ADEREF) + G(OP_ADEREF), \ + G(OP_ACAT) enum Opcodes { OPCODES(GEN_ENUM) diff --git a/src/vm.c b/src/vm.c index 411d7a7..3b4c682 100644 --- a/src/vm.c +++ b/src/vm.c @@ -71,6 +71,7 @@ void vm_exec(vm* self, program* prog) case OP_MKARRAY: vm_mkarray(self, param); break; case OP_ADEREF: vm_aderef(self); break; + case OP_ACAT: vm_acat(self); break; default: { fprintf(stderr, "unknown opcode %s\n", @@ -620,3 +621,38 @@ void vm_aderef(vm* self) self->pc++; } + +void vm_acat(vm* self) +{ + assert(self); + + value* rhs = vm_pop_value(self); + value* lhs = vm_pop_value(self); + + array* lhs_arr = lhs->val.array_val; + array* rhs_arr = rhs->val.array_val; + + array result_arr; + array_init(&result_arr, lhs->type->array_type); + + for (size_t i=0; ichildren.size; i++) + { + array_push(&result_arr, lhs_arr->children.data[i]); + } + + for (size_t i=0; ichildren.size; i++) + { + array_push(&result_arr, rhs_arr->children.data[i]); + } + + value* result = malloc(sizeof(value)); + value_init_array(result, &result_arr, lhs->lineno); + + array_free(&result_arr); + value_free(lhs); free(lhs); + value_free(rhs); free(rhs); + + vm_push_value(self, result); + + self->pc++; +} diff --git a/src/vm.h b/src/vm.h index 69ac1b0..4eae76d 100644 --- a/src/vm.h +++ b/src/vm.h @@ -55,5 +55,6 @@ void vm_cat(vm* self); void vm_mkarray(vm* self, int param); void vm_aderef(vm* self); +void vm_acat(vm* self); #endif diff --git a/tests/err_ty_array.wuz b/tests/err_ty_array.wuz index 5132e49..862288a 100644 --- a/tests/err_ty_array.wuz +++ b/tests/err_ty_array.wuz @@ -6,3 +6,5 @@ [1, 2, 3][3.14] [1, 2, 3][ [0, 1] ] [1, 2, 3][0, 0] +[1] + 1 +[[1, 2]] + [1] diff --git a/tests/test_array.wuz b/tests/test_array.wuz index a5dab54..cd90d22 100644 --- a/tests/test_array.wuz +++ b/tests/test_array.wuz @@ -16,8 +16,7 @@ assert "8" == ["3", "8", "9"][2 - 1] assert 7 == [[4, 6], [9, 2, 7], [3, 3, 2]][1, 2] assert 9 == [[4, 6], [9, 2, 7], [3, 3, 2]][[2, 9, 1][2], 0] - - - - +assert [1, 2] == [1] + [2] +assert [3, 4, 5, 6] == [3] + [4] + [5, 6] +assert [[2, 4], [6, 8]] == [[2, 4]] + [[6, 8]]