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);
|
compile_node(self, root->children.data[0], prog);
|
||||||
program_add_instr(prog, OP_AMUL, NO_PARAM);
|
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
|
else
|
||||||
{
|
{
|
||||||
compile_number(self, root, prog, OP_IMUL, OP_FMUL);
|
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);
|
compile_children(self, root, prog);
|
||||||
program_add_instr(prog, OP_ACAT, NO_PARAM);
|
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
|
else
|
||||||
{
|
{
|
||||||
compile_number(self, root, prog, OP_IADD, OP_FADD);
|
compile_number(self, root, prog, OP_IADD, OP_FADD);
|
||||||
|
@ -90,7 +100,6 @@ void compile_node(compiler* self, node* root, program* prog)
|
||||||
{
|
{
|
||||||
type* ty = compile_get_type(self, root);
|
type* ty = compile_get_type(self, root);
|
||||||
|
|
||||||
|
|
||||||
value val;
|
value val;
|
||||||
value_init_type(&val,
|
value_init_type(&val,
|
||||||
ty,
|
ty,
|
||||||
|
@ -255,14 +264,24 @@ type* compile_get_type(compiler* self, node* root)
|
||||||
else if (strcmp(root->value, "array") == 0)
|
else if (strcmp(root->value, "array") == 0)
|
||||||
{
|
{
|
||||||
type_init(ty, TY_ARRAY);
|
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
|
else
|
||||||
{
|
{
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"E(%d): cannot compile unknown type '%s'.'\n",
|
"E(%d): cannot compile unknown type '%s'.\n",
|
||||||
root->lineno,
|
root->lineno,
|
||||||
root->value);
|
NodeTypeStr[root->type]);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (size_t i=0; i<root->children.size; i++)
|
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(self);
|
||||||
assert(ast);
|
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)
|
if (ast->type == NODE_MUL)
|
||||||
{
|
{
|
||||||
int lhs = cstatic_resolve_base_type(self, ast->children.data[0]);
|
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;
|
return lhs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (lhs->base_type == TY_TYPE
|
||||||
|
&& rhs->base_type == TY_TYPE)
|
||||||
|
{
|
||||||
|
type_free(rhs);
|
||||||
|
free(rhs);
|
||||||
|
return lhs;
|
||||||
|
}
|
||||||
|
|
||||||
type_free(lhs);
|
type_free(lhs);
|
||||||
free(lhs);
|
free(lhs);
|
||||||
type_free(rhs);
|
type_free(rhs);
|
||||||
|
@ -238,6 +258,38 @@ int cstatic_check(cstatic* self, node* ast, char* msg, size_t size)
|
||||||
return 1;
|
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
|
// Array Operations
|
||||||
if (ast->type == NODE_ADD)
|
if (ast->type == NODE_ADD)
|
||||||
{
|
{
|
||||||
|
|
|
@ -31,7 +31,9 @@
|
||||||
G(OP_MKARRAY), \
|
G(OP_MKARRAY), \
|
||||||
G(OP_ADEREF), \
|
G(OP_ADEREF), \
|
||||||
G(OP_ACAT), \
|
G(OP_ACAT), \
|
||||||
G(OP_AMUL)
|
G(OP_AMUL), \
|
||||||
|
G(OP_TMUL), \
|
||||||
|
G(OP_TADD)
|
||||||
|
|
||||||
enum Opcodes {
|
enum Opcodes {
|
||||||
OPCODES(GEN_ENUM)
|
OPCODES(GEN_ENUM)
|
||||||
|
|
|
@ -34,9 +34,11 @@
|
||||||
%left MUL DIV MOD
|
%left MUL DIV MOD
|
||||||
%left POW
|
%left POW
|
||||||
%left NOT
|
%left NOT
|
||||||
%token OPAR CPAR OSQUARE CSQUARE COMMA
|
%token OPAR CPAR
|
||||||
|
%token OSQUARE CSQUARE COMMA
|
||||||
|
|
||||||
%type <n_children> expr_unop
|
%type <n_children> expr_unop
|
||||||
|
|
||||||
%%
|
%%
|
||||||
|
|
||||||
prog:
|
prog:
|
||||||
|
@ -263,8 +265,8 @@ expr_unop:
|
||||||
;
|
;
|
||||||
|
|
||||||
type_list:
|
type_list:
|
||||||
type { $$ = $1; }
|
expr { $$ = $1; }
|
||||||
| type_list COMMA type { $$ = $1 + $3; }
|
| type_list COMMA expr { $$ = $1 + $3; }
|
||||||
|
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|
63
src/type.c
63
src/type.c
|
@ -6,7 +6,7 @@ void type_init(type* self, int base_type)
|
||||||
{
|
{
|
||||||
assert(self);
|
assert(self);
|
||||||
self->base_type = base_type;
|
self->base_type = base_type;
|
||||||
|
self->kind = KIND_CONJUNCTION;
|
||||||
self->sub_types.size = 0;
|
self->sub_types.size = 0;
|
||||||
self->sub_types.capacity = 1;
|
self->sub_types.capacity = 1;
|
||||||
self->sub_types.data = malloc(sizeof(type*));
|
self->sub_types.data = malloc(sizeof(type*));
|
||||||
|
@ -18,6 +18,7 @@ void type_init_array(type* self, type* array_type)
|
||||||
assert(array_type);
|
assert(array_type);
|
||||||
type_init(self, TY_ARRAY);
|
type_init(self, TY_ARRAY);
|
||||||
type_add_sub_type(self, array_type);
|
type_add_sub_type(self, array_type);
|
||||||
|
self->kind = KIND_SEQUENTIAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void type_free(type* self)
|
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]);
|
type_add_sub_type(clone, self->sub_types.data[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
clone->kind = self->kind;
|
||||||
|
|
||||||
return clone;
|
return clone;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -84,6 +87,23 @@ int type_equals(type* self, type* rhs)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (self->kind != rhs->kind)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (self->kind != KIND_SEQUENTIAL)
|
||||||
|
{
|
||||||
|
for (int i=0; i<TY_TYPE_COUNT; i++)
|
||||||
|
{
|
||||||
|
if (type_count(self, i) != type_count(rhs, i))
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
for (size_t i=0; i<self->sub_types.size; i++)
|
for (size_t i=0; i<self->sub_types.size; i++)
|
||||||
{
|
{
|
||||||
if (!type_equals(self->sub_types.data[i],
|
if (!type_equals(self->sub_types.data[i],
|
||||||
|
@ -92,6 +112,7 @@ int type_equals(type* self, type* rhs)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -103,9 +124,20 @@ size_t type_str(type* self, char* buffer, size_t size)
|
||||||
TypesStr[self->base_type] + strlen("TY_"));
|
TypesStr[self->base_type] + strlen("TY_"));
|
||||||
|
|
||||||
if (self->sub_types.size > 0)
|
if (self->sub_types.size > 0)
|
||||||
|
{
|
||||||
|
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, "<");
|
sz += snprintf(buffer + sz, size - sz, "<");
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (size_t i=0; i<self->sub_types.size; i++)
|
for (size_t i=0; i<self->sub_types.size; i++)
|
||||||
{
|
{
|
||||||
|
@ -118,9 +150,38 @@ size_t type_str(type* self, char* buffer, size_t size)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (self->sub_types.size > 0)
|
if (self->sub_types.size > 0)
|
||||||
|
{
|
||||||
|
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, ">");
|
sz += snprintf(buffer + sz, size - sz, ">");
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return 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[];
|
extern char const* TypesStr[];
|
||||||
|
|
||||||
|
enum TypeKind {
|
||||||
|
KIND_DISJUNCTION,
|
||||||
|
KIND_CONJUNCTION,
|
||||||
|
KIND_SEQUENTIAL
|
||||||
|
};
|
||||||
|
|
||||||
typedef struct type {
|
typedef struct type {
|
||||||
int base_type;
|
int base_type;
|
||||||
|
int kind;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
size_t size;
|
size_t size;
|
||||||
size_t capacity;
|
size_t capacity;
|
||||||
|
@ -38,4 +46,5 @@ type* type_new_clone(type* self);
|
||||||
int type_equals(type* self, type* rhs);
|
int type_equals(type* self, type* rhs);
|
||||||
size_t type_str(type* self, char* buffer, size_t size);
|
size_t type_str(type* self, char* buffer, size_t size);
|
||||||
|
|
||||||
|
int type_count(type* self, int base_type);
|
||||||
#endif
|
#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_ADEREF: vm_aderef(self); break;
|
||||||
case OP_ACAT: vm_acat(self); break;
|
case OP_ACAT: vm_acat(self); break;
|
||||||
case OP_AMUL: vm_amul(self); break;
|
case OP_AMUL: vm_amul(self); break;
|
||||||
|
case OP_TMUL: vm_tmul(self); break;
|
||||||
|
case OP_TADD: vm_tadd(self); break;
|
||||||
|
|
||||||
default: {
|
default: {
|
||||||
fprintf(stderr, "unknown opcode %s\n",
|
fprintf(stderr, "unknown opcode %s\n",
|
||||||
|
@ -657,6 +659,7 @@ void vm_acat(vm* self)
|
||||||
|
|
||||||
self->pc++;
|
self->pc++;
|
||||||
}
|
}
|
||||||
|
|
||||||
void vm_amul(vm* self)
|
void vm_amul(vm* self)
|
||||||
{
|
{
|
||||||
assert(self);
|
assert(self);
|
||||||
|
@ -689,3 +692,51 @@ void vm_amul(vm* self)
|
||||||
|
|
||||||
self->pc++;
|
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_aderef(vm* self);
|
||||||
void vm_acat(vm* self);
|
void vm_acat(vm* self);
|
||||||
void vm_amul(vm* self);
|
void vm_amul(vm* self);
|
||||||
|
void vm_tmul(vm* self);
|
||||||
|
void vm_tadd(vm* self);
|
||||||
|
|
||||||
#endif
|
#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 bool != int
|
||||||
assert array<float> != array<int>
|
assert array<float> != array<int>
|
||||||
assert array<array<int>> != 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