Compare commits

...

2 Commits

Author SHA1 Message Date
bog 0b44732961 ADD: type literals. 2023-08-24 23:28:45 +02:00
bog 7a4e71bf14 REF: array sub types. 2023-08-24 21:28:54 +02:00
12 changed files with 280 additions and 44 deletions

View File

@ -86,6 +86,24 @@ void compile_node(compiler* self, node* root, program* prog)
compile_number(self, root, prog, OP_IADD, OP_FADD); compile_number(self, root, prog, OP_IADD, OP_FADD);
} }
} }
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);
type_free(ty);
free(ty);
value_free(&val);
}
else if (root->type == NODE_BOOLEAN) else if (root->type == NODE_BOOLEAN)
{ {
value val; value val;
@ -208,6 +226,56 @@ void compile_children(compiler* self, node* root, program* prog)
} }
} }
type* compile_get_type(compiler* self, node* root)
{
assert(self);
assert(root);
type* ty = malloc(sizeof(type));
if (strcmp(root->value, "int") == 0)
{
type_init(ty, TY_INTEGER);
}
else if (strcmp(root->value, "float") == 0)
{
type_init(ty, TY_FLOAT);
}
else if (strcmp(root->value, "str") == 0)
{
type_init(ty, TY_STRING);
}
else if (strcmp(root->value, "bool") == 0)
{
type_init(ty, TY_BOOLEAN);
}
else if (strcmp(root->value, "array") == 0)
{
type_init(ty, TY_ARRAY);
}
else
{
fprintf(stderr,
"E(%d): cannot compile unknown type '%s'.'\n",
root->lineno,
root->value);
}
for (size_t i=0; i<root->children.size; i++)
{
type* sub = compile_get_type(self, root->children.data[i]);
type_add_sub_type(ty, sub);
type_free(sub);
free(sub);
}
return ty;
}
void compile_number(compiler* self, node* root, program* prog, void compile_number(compiler* self, node* root, program* prog,
int integer_op, int integer_op,
int float_op) int float_op)

View File

@ -15,6 +15,8 @@ void compiler_free(compiler* self);
void compile_node(compiler* self, node* root, program* prog); void compile_node(compiler* self, node* root, program* prog);
void compile_children(compiler* self, node* root, program* prog); void compile_children(compiler* self, node* root, program* prog);
type* compile_get_type(compiler* self, node* root);
void compile_number(compiler* self, node* root, program* prog, void compile_number(compiler* self, node* root, program* prog,
int integer_op, int integer_op,
int float_op); int float_op);

View File

@ -105,6 +105,11 @@ type* cstatic_resolve_new(cstatic* self, node* ast)
return cstatic_new_type(self, TY_STRING); return cstatic_new_type(self, TY_STRING);
} }
else if (ast->type == NODE_TYPE)
{
return cstatic_new_type(self, TY_TYPE);
}
else if (ast->type == NODE_ARRAY) else if (ast->type == NODE_ARRAY)
{ {
assert(ast->children.size > 0); assert(ast->children.size > 0);

View File

@ -13,13 +13,21 @@ BOOLEAN true|false
INTEGER -?[0-9]+ INTEGER -?[0-9]+
FLOAT -?[0-9]+\.[0-9]+ FLOAT -?[0-9]+\.[0-9]+
STRING \"[^"]*\" STRING \"[^"]*\"
TYPE (int|float|bool|str|array)
%% %%
{COMMENT} {} {COMMENT} {}
"\n" { line++; } "\n" { line++; }
{WHITESPACES} {} {WHITESPACES} {}
{TYPE} {
yylval.str = str_new(yytext);
return TYPE;
}
"assert" { return ASSERT; } "assert" { return ASSERT; }
"<" { return LT; }
">" { return GT; }
"," { return COMMA; } "," { return COMMA; }
"+" { return ADD; } "+" { return ADD; }
"-" { return SUB; } "-" { return SUB; }

View File

@ -4,7 +4,7 @@
#define NODE_TYPE(G) \ #define NODE_TYPE(G) \
G(NODE_PROG), \ G(NODE_PROG), \
G(NODE_BOOLEAN), G(NODE_INTEGER), G(NODE_FLOAT), \ G(NODE_BOOLEAN), G(NODE_INTEGER), G(NODE_FLOAT), \
G(NODE_STRING), \ G(NODE_STRING), G(NODE_TYPE), \
G(NODE_AND), G(NODE_OR), G(NODE_NOT), \ G(NODE_AND), G(NODE_OR), G(NODE_NOT), \
G(NODE_EQ), G(NODE_NE), \ G(NODE_EQ), G(NODE_NE), \
G(NODE_ASSERT), \ G(NODE_ASSERT), \

View File

@ -22,18 +22,21 @@
}; };
%left ASSERT %left ASSERT
%token <str> BOOLEAN INTEGER FLOAT STRING %token LT GT
%type <n_children> expr exprs prog array arrays builtins %token <str> TYPE BOOLEAN INTEGER FLOAT STRING
%type <n_children> expr_list %type <n_children> expr exprs prog array builtins
%type <n_children> expr_list type type_list
%left EQ NE %left EQ NE
%left AND %left AND
%left OR %left OR
%left ADD SUB %left ADD
%left SUB
%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 OSQUARE CSQUARE COMMA
%type <n_children> expr_unop
%% %%
prog: prog:
@ -47,10 +50,17 @@ prog:
| exprs { | exprs {
node* n = malloc(sizeof(node)); node* n = malloc(sizeof(node));
node_init(n, NODE_PROG, "", line); node_init(n, NODE_PROG, "", line);
size_t const SZ = $1;
node* all[SZ];
for (size_t i=0; i<$1; i++) for (size_t i=0; i<SZ; i++)
{ {
node_add_child(n, stack_pop()); all[i] = stack_pop();
}
for (size_t i=0; i<SZ; i++)
{
node_add_child(n, all[SZ - 1 - i]);
} }
stack_push(n); stack_push(n);
@ -105,23 +115,10 @@ expr:
$$ = 1; $$ = 1;
} }
| ADD expr {
node *n = malloc(sizeof(node));
node_init(n, NODE_UADD, "", line);
node_add_child(n, stack_pop());
stack_push(n);
$$ = 1;
}
| SUB expr { | expr_unop {}
node *n = malloc(sizeof(node));
node_init(n, NODE_USUB, "", line);
node_add_child(n, stack_pop());
stack_push(n);
$$ = 1;
}
| expr ADD expr { | expr ADD expr{
node *n = malloc(sizeof(node)); node *n = malloc(sizeof(node));
node_init(n, NODE_ADD, "", line); node_init(n, NODE_ADD, "", line);
node* rhs = stack_pop(); node* rhs = stack_pop();
@ -143,6 +140,7 @@ expr:
$$ = 1; $$ = 1;
} }
| expr MUL expr { | expr MUL expr {
node *n = malloc(sizeof(node)); node *n = malloc(sizeof(node));
node_init(n, NODE_MUL, "", line); node_init(n, NODE_MUL, "", line);
@ -246,9 +244,65 @@ expr:
; ;
builtins: expr_unop:
ADD expr {
node *n = malloc(sizeof(node));
node_init(n, NODE_UADD, "", line);
node_add_child(n, stack_pop());
stack_push(n);
$$ = 1;
}
STRING { | SUB expr {
node *n = malloc(sizeof(node));
node_init(n, NODE_USUB, "", line);
node_add_child(n, stack_pop());
stack_push(n);
$$ = 1;
}
;
type_list:
type { $$ = $1; }
| type_list COMMA type { $$ = $1 + $3; }
;
type:
TYPE LT type_list GT {
node* n = malloc(sizeof(node));
node_init(n, NODE_TYPE, $1, line);
free($1);
size_t const SZ = $3;
node* all[SZ];
for (size_t i=0; i<SZ; i++)
{
all[i] = stack_pop();
}
for (size_t i=0; i<SZ; i++)
{
node_add_child(n, all[SZ - 1 - i]);
}
stack_push(n);
$$ = 1;
}
| TYPE {
node* n = malloc(sizeof(node));
node_init(n, NODE_TYPE, $1, line);
free($1);
stack_push(n);
$$ = 1;
}
;
builtins:
type {}
| STRING {
node* n = malloc(sizeof(node)); node* n = malloc(sizeof(node));
size_t const SZ = strlen($1); size_t const SZ = strlen($1);
char str[SZ - 2]; char str[SZ - 2];

View File

@ -6,7 +6,10 @@ void type_init(type* self, int base_type)
{ {
assert(self); assert(self);
self->base_type = base_type; self->base_type = base_type;
self->array_type = NULL;
self->sub_types.size = 0;
self->sub_types.capacity = 1;
self->sub_types.data = malloc(sizeof(type*));
} }
void type_init_array(type* self, type* array_type) void type_init_array(type* self, type* array_type)
@ -14,18 +17,41 @@ void type_init_array(type* self, type* array_type)
assert(self); assert(self);
assert(array_type); assert(array_type);
type_init(self, TY_ARRAY); type_init(self, TY_ARRAY);
self->array_type = type_new_clone(array_type); type_add_sub_type(self, array_type);
} }
void type_free(type* self) void type_free(type* self)
{ {
assert(self); assert(self);
if (self->array_type != NULL) for (size_t i=0; i<self->sub_types.size; i++)
{ {
type_free(self->array_type); type_free(self->sub_types.data[i]);
free(self->array_type); free(self->sub_types.data[i]);
} }
free(self->sub_types.data);
self->sub_types.size = 0;
self->sub_types.capacity = 0;
self->sub_types.data = NULL;
}
void type_add_sub_type(type* self, type* rhs)
{
assert(self);
assert(rhs);
if (self->sub_types.size >= self->sub_types.capacity)
{
self->sub_types.capacity *= 2;
self->sub_types.data =
realloc(self->sub_types.data,
sizeof(type*) * self->sub_types.capacity);
}
self->sub_types.data[self->sub_types.size] = type_new_clone(rhs);
self->sub_types.size++;
} }
type* type_new_clone(type* self) type* type_new_clone(type* self)
@ -35,9 +61,9 @@ type* type_new_clone(type* self)
type* clone = malloc(sizeof(type)); type* clone = malloc(sizeof(type));
type_init(clone, self->base_type); type_init(clone, self->base_type);
if (self->array_type) for (size_t i=0; i<self->sub_types.size; i++)
{ {
clone->array_type = type_new_clone(self->array_type); type_add_sub_type(clone, self->sub_types.data[i]);
} }
return clone; return clone;
@ -52,16 +78,22 @@ int type_equals(type* self, type* rhs)
{ {
return 0; return 0;
} }
if (self->base_type == TY_ARRAY) if (self->sub_types.size != rhs->sub_types.size)
{ {
assert(self->array_type); return 0;
assert(rhs->array_type); }
return type_equals(self->array_type, rhs->array_type);
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;
}
} }
return 1; return 1;
} }
size_t type_str(type* self, char* buffer, size_t size) size_t type_str(type* self, char* buffer, size_t size)
@ -69,11 +101,24 @@ size_t type_str(type* self, char* buffer, size_t size)
assert(self); assert(self);
size_t sz = snprintf(buffer, size, "%s", size_t sz = snprintf(buffer, size, "%s",
TypesStr[self->base_type] + strlen("TY_")); TypesStr[self->base_type] + strlen("TY_"));
if (self->base_type == TY_ARRAY) if (self->sub_types.size > 0)
{ {
sz += snprintf(buffer + sz, size - sz, "<"); sz += snprintf(buffer + sz, size - sz, "<");
sz += type_str(self->array_type, buffer + sz, size - sz); }
for (size_t i=0; i<self->sub_types.size; i++)
{
if (i > 0)
{
sz += snprintf(buffer + sz, size - sz, ", ");
}
sz += type_str(self->sub_types.data[i], buffer + sz, size - sz);
}
if (self->sub_types.size > 0)
{
sz += snprintf(buffer + sz, size - sz, ">"); sz += snprintf(buffer + sz, size - sz, ">");
} }

View File

@ -10,6 +10,7 @@
G(TY_FLOAT), \ G(TY_FLOAT), \
G(TY_STRING), \ G(TY_STRING), \
G(TY_ARRAY), \ G(TY_ARRAY), \
G(TY_TYPE), \
G(TY_TYPE_COUNT) G(TY_TYPE_COUNT)
enum Types { enum Types {
@ -20,13 +21,19 @@ extern char const* TypesStr[];
typedef struct type { typedef struct type {
int base_type; int base_type;
struct type* array_type; struct {
size_t size;
size_t capacity;
struct type** data;
} sub_types;
} type; } type;
void type_init(type* self, int base_type); void type_init(type* self, int base_type);
void type_init_array(type* self, type* array_type); void type_init_array(type* self, type* array_type);
void type_free(type* self); void type_free(type* self);
void type_add_sub_type(type* self, type* rhs);
type* type_new_clone(type* self); 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);

View File

@ -56,10 +56,29 @@ void value_init_array(value* self, array* arr, int lineno)
type_init_array(self->type, arr->type); type_init_array(self->type, arr->type);
} }
void value_init_type(value* self, type* ty, int lineno)
{
assert(self);
assert(ty);
self->val.type_val = type_new_clone(ty);
self->lineno = lineno;
self->type = malloc(sizeof(type));
type_init(self->type, TY_TYPE);
}
void value_free(value* self) void value_free(value* self)
{ {
assert(self); assert(self);
if (self->type->base_type == TY_TYPE
&& self->val.type_val != NULL)
{
type_free(self->val.type_val);
free(self->val.type_val);
self->val.type_val = NULL;
}
if (self->type->base_type == TY_STRING if (self->type->base_type == TY_STRING
&& self->val.string != NULL) && self->val.string != NULL)
{ {
@ -92,6 +111,11 @@ value* value_new_clone(value* self)
clone->val.string = str_new(self->val.string); clone->val.string = str_new(self->val.string);
} }
if (self->type->base_type == TY_TYPE)
{
clone->val.type_val = type_new_clone(self->val.type_val);
}
if (self->type->base_type == TY_ARRAY) if (self->type->base_type == TY_ARRAY)
{ {
clone->val.array_val = array_new_clone(self->val.array_val); clone->val.array_val = array_new_clone(self->val.array_val);
@ -133,6 +157,11 @@ int value_equals(value* self, value* rhs)
return strcmp(self->val.string, rhs->val.string) == 0; return strcmp(self->val.string, rhs->val.string) == 0;
} }
if (self->type->base_type == TY_TYPE)
{
return type_equals(self->val.type_val, rhs->val.type_val);
}
if (self->type->base_type == TY_ARRAY) if (self->type->base_type == TY_ARRAY)
{ {
return array_equals(self->val.array_val, rhs->val.array_val); return array_equals(self->val.array_val, rhs->val.array_val);
@ -167,8 +196,11 @@ size_t value_str(value* self, char* buffer, size_t size)
case TY_INTEGER: case TY_INTEGER:
return snprintf(buffer, size, "%d", return snprintf(buffer, size, "%d",
self->val.integer); self->val.integer);
case TY_TYPE:
return type_str(self->val.type_val, buffer, size);
default: { default: {
fprintf(stderr, "E: unknown value"); fprintf(stderr, "E: cannot stringify unknown value");
exit(-1); exit(-1);
} }
} }

View File

@ -14,6 +14,7 @@ typedef struct {
float real_float; float real_float;
char* string; char* string;
array* array_val; array* array_val;
type* type_val;
} val; } val;
} value; } value;
@ -22,6 +23,7 @@ void value_init_integer(value* self, int integer, int lineno);
void value_init_float(value* self, float real_float, int lineno); void value_init_float(value* self, float real_float, int lineno);
void value_init_string(value* self, char* string, int lineno); void value_init_string(value* self, char* string, int lineno);
void value_init_array(value* self, array* arr, int lineno); void value_init_array(value* self, array* arr, int lineno);
void value_init_type(value* self, type* ty, int lineno);
void value_free(value* self); void value_free(value* self);

View File

@ -634,7 +634,7 @@ void vm_acat(vm* self)
array* rhs_arr = rhs->val.array_val; array* rhs_arr = rhs->val.array_val;
array result_arr; array result_arr;
array_init(&result_arr, lhs->type->array_type); array_init(&result_arr, lhs->type->sub_types.data[0]);
for (size_t i=0; i<lhs_arr->children.size; i++) for (size_t i=0; i<lhs_arr->children.size; i++)
{ {
@ -668,7 +668,7 @@ void vm_amul(vm* self)
int count = rhs->val.integer; int count = rhs->val.integer;
array result_arr; array result_arr;
array_init(&result_arr, lhs->type->array_type); array_init(&result_arr, lhs->type->sub_types.data[0]);
for (int j=0; j<count; j++) for (int j=0; j<count; j++)
{ {
for (size_t i=0; i<arr->children.size; i++) for (size_t i=0; i<arr->children.size; i++)

13
tests/test_types.wuz Normal file
View File

@ -0,0 +1,13 @@
assert int == int
assert float == float
assert str == str
assert bool == bool
assert array<int> == array<int>
assert array<array<int>> == array<array<int>>
assert int != float
assert float != str
assert str != bool
assert bool != int
assert array<float> != array<int>
assert array<array<int>> != array<int>