ADD: type addition and multiplication.

main
bog 2023-08-25 01:50:18 +02:00
parent 0b44732961
commit 9ca893dff5
10 changed files with 239 additions and 19 deletions

View File

@ -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);
@ -90,7 +100,6 @@ void compile_node(compiler* self, node* root, program* prog)
{
type* ty = compile_get_type(self, root);
value val;
value_init_type(&val,
ty,
@ -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++)

View File

@ -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);
@ -238,6 +258,38 @@ 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)
{

View File

@ -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)

View File

@ -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:
@ -263,8 +265,8 @@ expr_unop:
;
type_list:
type { $$ = $1; }
| type_list COMMA type { $$ = $1 + $3; }
expr { $$ = $1; }
| type_list COMMA expr { $$ = $1 + $3; }
;

View File

@ -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,6 +87,23 @@ int type_equals(type* self, type* rhs)
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++)
{
if (!type_equals(self->sub_types.data[i],
@ -92,6 +112,7 @@ int type_equals(type* self, type* rhs)
return 0;
}
}
}
return 1;
}
@ -103,9 +124,20 @@ size_t type_str(type* self, char* buffer, size_t size)
TypesStr[self->base_type] + strlen("TY_"));
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, "<");
}
}
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->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;
}

View File

@ -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

View File

@ -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++;
}

View File

@ -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

4
tests/err_ty_type.wuz Normal file
View File

@ -0,0 +1,4 @@
int * 5
str * "salut"
str + "salut"
float + 1.2

View File

@ -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>