ADD: type addition and multiplication.
parent
0b44732961
commit
9ca893dff5
|
@ -56,6 +56,11 @@ void compile_node(compiler* self, node* root, program* prog)
|
|||
compile_node(self, root->children.data[0], prog);
|
||||
program_add_instr(prog, OP_AMUL, NO_PARAM);
|
||||
}
|
||||
else if (rhs == TY_TYPE && lhs == TY_TYPE)
|
||||
{
|
||||
compile_children(self, root, prog);
|
||||
program_add_instr(prog, OP_TMUL, NO_PARAM);
|
||||
}
|
||||
else
|
||||
{
|
||||
compile_number(self, root, prog, OP_IMUL, OP_FMUL);
|
||||
|
@ -81,6 +86,11 @@ void compile_node(compiler* self, node* root, program* prog)
|
|||
compile_children(self, root, prog);
|
||||
program_add_instr(prog, OP_ACAT, NO_PARAM);
|
||||
}
|
||||
else if (lhs == rhs && lhs == TY_TYPE)
|
||||
{
|
||||
compile_children(self, root, prog);
|
||||
program_add_instr(prog, OP_TADD, NO_PARAM);
|
||||
}
|
||||
else
|
||||
{
|
||||
compile_number(self, root, prog, OP_IADD, OP_FADD);
|
||||
|
@ -89,13 +99,12 @@ void compile_node(compiler* self, node* root, program* prog)
|
|||
else if (root->type == NODE_TYPE)
|
||||
{
|
||||
type* ty = compile_get_type(self, root);
|
||||
|
||||
|
||||
|
||||
value val;
|
||||
value_init_type(&val,
|
||||
ty,
|
||||
root->lineno);
|
||||
|
||||
|
||||
size_t idx = program_add_pool(prog, &val);
|
||||
program_add_instr(prog, OP_PUSH, idx);
|
||||
|
||||
|
@ -255,14 +264,24 @@ type* compile_get_type(compiler* self, node* root)
|
|||
else if (strcmp(root->value, "array") == 0)
|
||||
{
|
||||
type_init(ty, TY_ARRAY);
|
||||
ty->kind = KIND_SEQUENTIAL;
|
||||
}
|
||||
else if (root->type == NODE_ADD)
|
||||
{
|
||||
type_init(ty, TY_TYPE);
|
||||
ty->kind = KIND_DISJUNCTION;
|
||||
}
|
||||
else if (root->type == NODE_MUL)
|
||||
{
|
||||
type_init(ty, TY_TYPE);
|
||||
ty->kind = KIND_CONJUNCTION;
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
fprintf(stderr,
|
||||
"E(%d): cannot compile unknown type '%s'.'\n",
|
||||
"E(%d): cannot compile unknown type '%s'.\n",
|
||||
root->lineno,
|
||||
root->value);
|
||||
NodeTypeStr[root->type]);
|
||||
}
|
||||
|
||||
for (size_t i=0; i<root->children.size; i++)
|
||||
|
|
|
@ -35,6 +35,18 @@ type* cstatic_resolve_new(cstatic* self, node* ast)
|
|||
assert(self);
|
||||
assert(ast);
|
||||
|
||||
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_TYPE && rhs->base_type == TY_TYPE)
|
||||
{
|
||||
type_free(rhs); free(rhs);
|
||||
return lhs;
|
||||
}
|
||||
}
|
||||
|
||||
if (ast->type == NODE_MUL)
|
||||
{
|
||||
int lhs = cstatic_resolve_base_type(self, ast->children.data[0]);
|
||||
|
@ -67,6 +79,14 @@ type* cstatic_resolve_new(cstatic* self, node* ast)
|
|||
return lhs;
|
||||
}
|
||||
|
||||
if (lhs->base_type == TY_TYPE
|
||||
&& rhs->base_type == TY_TYPE)
|
||||
{
|
||||
type_free(rhs);
|
||||
free(rhs);
|
||||
return lhs;
|
||||
}
|
||||
|
||||
type_free(lhs);
|
||||
free(lhs);
|
||||
type_free(rhs);
|
||||
|
@ -237,7 +257,39 @@ int cstatic_check(cstatic* self, node* ast, char* msg, size_t size)
|
|||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
// Types Operations
|
||||
if (ast->type == NODE_MUL)
|
||||
{
|
||||
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_TYPE && rhs->base_type == TY_TYPE)
|
||||
{
|
||||
type_free(lhs); free(lhs);
|
||||
type_free(rhs); free(rhs);
|
||||
return 1;
|
||||
}
|
||||
|
||||
type_free(lhs); free(lhs);
|
||||
type_free(rhs); free(rhs);
|
||||
}
|
||||
|
||||
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_TYPE && rhs->base_type == TY_TYPE)
|
||||
{
|
||||
type_free(lhs); free(lhs);
|
||||
type_free(rhs); free(rhs);
|
||||
return 1;
|
||||
}
|
||||
|
||||
type_free(lhs); free(lhs);
|
||||
type_free(rhs); free(rhs);
|
||||
}
|
||||
// Array Operations
|
||||
if (ast->type == NODE_ADD)
|
||||
{
|
||||
|
|
|
@ -31,7 +31,9 @@
|
|||
G(OP_MKARRAY), \
|
||||
G(OP_ADEREF), \
|
||||
G(OP_ACAT), \
|
||||
G(OP_AMUL)
|
||||
G(OP_AMUL), \
|
||||
G(OP_TMUL), \
|
||||
G(OP_TADD)
|
||||
|
||||
enum Opcodes {
|
||||
OPCODES(GEN_ENUM)
|
||||
|
|
10
src/parser.y
10
src/parser.y
|
@ -34,9 +34,11 @@
|
|||
%left MUL DIV MOD
|
||||
%left POW
|
||||
%left NOT
|
||||
%token OPAR CPAR OSQUARE CSQUARE COMMA
|
||||
%token OPAR CPAR
|
||||
%token OSQUARE CSQUARE COMMA
|
||||
|
||||
%type <n_children> expr_unop
|
||||
|
||||
%%
|
||||
|
||||
prog:
|
||||
|
@ -118,7 +120,7 @@ expr:
|
|||
|
||||
| expr_unop {}
|
||||
|
||||
| expr ADD expr{
|
||||
| expr ADD expr{
|
||||
node *n = malloc(sizeof(node));
|
||||
node_init(n, NODE_ADD, "", line);
|
||||
node* rhs = stack_pop();
|
||||
|
@ -263,8 +265,8 @@ expr_unop:
|
|||
;
|
||||
|
||||
type_list:
|
||||
type { $$ = $1; }
|
||||
| type_list COMMA type { $$ = $1 + $3; }
|
||||
expr { $$ = $1; }
|
||||
| type_list COMMA expr { $$ = $1 + $3; }
|
||||
|
||||
;
|
||||
|
||||
|
|
75
src/type.c
75
src/type.c
|
@ -6,7 +6,7 @@ void type_init(type* self, int base_type)
|
|||
{
|
||||
assert(self);
|
||||
self->base_type = base_type;
|
||||
|
||||
self->kind = KIND_CONJUNCTION;
|
||||
self->sub_types.size = 0;
|
||||
self->sub_types.capacity = 1;
|
||||
self->sub_types.data = malloc(sizeof(type*));
|
||||
|
@ -18,6 +18,7 @@ void type_init_array(type* self, type* array_type)
|
|||
assert(array_type);
|
||||
type_init(self, TY_ARRAY);
|
||||
type_add_sub_type(self, array_type);
|
||||
self->kind = KIND_SEQUENTIAL;
|
||||
}
|
||||
|
||||
void type_free(type* self)
|
||||
|
@ -66,6 +67,8 @@ type* type_new_clone(type* self)
|
|||
type_add_sub_type(clone, self->sub_types.data[i]);
|
||||
}
|
||||
|
||||
clone->kind = self->kind;
|
||||
|
||||
return clone;
|
||||
}
|
||||
|
||||
|
@ -84,12 +87,30 @@ int type_equals(type* self, type* rhs)
|
|||
return 0;
|
||||
}
|
||||
|
||||
for (size_t i=0; i<self->sub_types.size; i++)
|
||||
if (self->kind != rhs->kind)
|
||||
{
|
||||
if (!type_equals(self->sub_types.data[i],
|
||||
rhs->sub_types.data[i]))
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (self->kind != KIND_SEQUENTIAL)
|
||||
{
|
||||
for (int i=0; i<TY_TYPE_COUNT; i++)
|
||||
{
|
||||
return 0;
|
||||
if (type_count(self, i) != type_count(rhs, i))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (size_t i=0; i<self->sub_types.size; i++)
|
||||
{
|
||||
if (!type_equals(self->sub_types.data[i],
|
||||
rhs->sub_types.data[i]))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -104,7 +125,18 @@ size_t type_str(type* self, char* buffer, size_t size)
|
|||
|
||||
if (self->sub_types.size > 0)
|
||||
{
|
||||
sz += snprintf(buffer + sz, size - sz, "<");
|
||||
if (self->kind == KIND_CONJUNCTION)
|
||||
{
|
||||
sz += snprintf(buffer + sz, size - sz, "(");
|
||||
}
|
||||
else if (self->kind == KIND_DISJUNCTION)
|
||||
{
|
||||
sz += snprintf(buffer + sz, size - sz, "[");
|
||||
}
|
||||
else
|
||||
{
|
||||
sz += snprintf(buffer + sz, size - sz, "<");
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t i=0; i<self->sub_types.size; i++)
|
||||
|
@ -119,8 +151,37 @@ size_t type_str(type* self, char* buffer, size_t size)
|
|||
|
||||
if (self->sub_types.size > 0)
|
||||
{
|
||||
sz += snprintf(buffer + sz, size - sz, ">");
|
||||
if (self->kind == KIND_CONJUNCTION)
|
||||
{
|
||||
sz += snprintf(buffer + sz, size - sz, ")");
|
||||
}
|
||||
else if (self->kind == KIND_DISJUNCTION)
|
||||
{
|
||||
sz += snprintf(buffer + sz, size - sz, "]");
|
||||
}
|
||||
else
|
||||
{
|
||||
sz += snprintf(buffer + sz, size - sz, ">");
|
||||
}
|
||||
}
|
||||
|
||||
return sz;
|
||||
}
|
||||
|
||||
int type_count(type* self, int base_type)
|
||||
{
|
||||
assert(self);
|
||||
int n = 0;
|
||||
|
||||
if (self->base_type == base_type)
|
||||
{
|
||||
n = 1;
|
||||
}
|
||||
|
||||
for (size_t i=0; i<self->sub_types.size; i++)
|
||||
{
|
||||
n += type_count(self->sub_types.data[i], base_type);
|
||||
}
|
||||
|
||||
return n;
|
||||
}
|
||||
|
|
|
@ -19,8 +19,16 @@ enum Types {
|
|||
|
||||
extern char const* TypesStr[];
|
||||
|
||||
enum TypeKind {
|
||||
KIND_DISJUNCTION,
|
||||
KIND_CONJUNCTION,
|
||||
KIND_SEQUENTIAL
|
||||
};
|
||||
|
||||
typedef struct type {
|
||||
int base_type;
|
||||
int kind;
|
||||
|
||||
struct {
|
||||
size_t size;
|
||||
size_t capacity;
|
||||
|
@ -38,4 +46,5 @@ type* type_new_clone(type* self);
|
|||
int type_equals(type* self, type* rhs);
|
||||
size_t type_str(type* self, char* buffer, size_t size);
|
||||
|
||||
int type_count(type* self, int base_type);
|
||||
#endif
|
||||
|
|
51
src/vm.c
51
src/vm.c
|
@ -73,6 +73,8 @@ void vm_exec(vm* self, program* prog)
|
|||
case OP_ADEREF: vm_aderef(self); break;
|
||||
case OP_ACAT: vm_acat(self); break;
|
||||
case OP_AMUL: vm_amul(self); break;
|
||||
case OP_TMUL: vm_tmul(self); break;
|
||||
case OP_TADD: vm_tadd(self); break;
|
||||
|
||||
default: {
|
||||
fprintf(stderr, "unknown opcode %s\n",
|
||||
|
@ -657,6 +659,7 @@ void vm_acat(vm* self)
|
|||
|
||||
self->pc++;
|
||||
}
|
||||
|
||||
void vm_amul(vm* self)
|
||||
{
|
||||
assert(self);
|
||||
|
@ -689,3 +692,51 @@ void vm_amul(vm* self)
|
|||
|
||||
self->pc++;
|
||||
}
|
||||
|
||||
void vm_tmul(vm* self)
|
||||
{
|
||||
assert(self);
|
||||
|
||||
value* rhs = vm_pop_value(self);
|
||||
value* lhs = vm_pop_value(self);
|
||||
type ty;
|
||||
type_init(&ty, TY_TYPE);
|
||||
|
||||
type_add_sub_type(&ty, lhs->val.type_val);
|
||||
type_add_sub_type(&ty, rhs->val.type_val);
|
||||
|
||||
value* val = malloc(sizeof(value));
|
||||
value_init_type(val, &ty, lhs->lineno);
|
||||
|
||||
vm_push_value(self, val);
|
||||
|
||||
type_free(&ty);
|
||||
value_free(lhs); free(lhs);
|
||||
value_free(rhs); free(rhs);
|
||||
|
||||
self->pc++;
|
||||
}
|
||||
|
||||
void vm_tadd(vm* self)
|
||||
{
|
||||
assert(self);
|
||||
|
||||
value* rhs = vm_pop_value(self);
|
||||
value* lhs = vm_pop_value(self);
|
||||
type ty;
|
||||
type_init(&ty, TY_TYPE);
|
||||
ty.kind = KIND_DISJUNCTION;
|
||||
type_add_sub_type(&ty, lhs->val.type_val);
|
||||
type_add_sub_type(&ty, rhs->val.type_val);
|
||||
|
||||
value* val = malloc(sizeof(value));
|
||||
value_init_type(val, &ty, lhs->lineno);
|
||||
|
||||
vm_push_value(self, val);
|
||||
|
||||
type_free(&ty);
|
||||
value_free(lhs); free(lhs);
|
||||
value_free(rhs); free(rhs);
|
||||
|
||||
self->pc++;
|
||||
}
|
||||
|
|
2
src/vm.h
2
src/vm.h
|
@ -57,5 +57,7 @@ void vm_mkarray(vm* self, int param);
|
|||
void vm_aderef(vm* self);
|
||||
void vm_acat(vm* self);
|
||||
void vm_amul(vm* self);
|
||||
void vm_tmul(vm* self);
|
||||
void vm_tadd(vm* self);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
int * 5
|
||||
str * "salut"
|
||||
str + "salut"
|
||||
float + 1.2
|
|
@ -11,3 +11,21 @@ assert str != bool
|
|||
assert bool != int
|
||||
assert array<float> != array<int>
|
||||
assert array<array<int>> != array<int>
|
||||
|
||||
assert str * float == str * float
|
||||
assert str * float * array<int> == str * float * array<int>
|
||||
assert str * float * array<float> != str * float * array<int>
|
||||
|
||||
assert str + float == str + float
|
||||
assert (str + float) * int == (str + float) * int
|
||||
assert (float + float) * int != (str + float) * int
|
||||
|
||||
assert array<int + float> == array<int + float>
|
||||
assert array<int * float> != array<int + float>
|
||||
|
||||
assert int + float == float + int
|
||||
assert int * bool == bool * int
|
||||
assert int * str * bool == bool * int * str
|
||||
assert array<int, float> != array<float, int>
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue