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);
}
}
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)
{
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,
int integer_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_children(compiler* self, node* root, program* prog);
type* compile_get_type(compiler* self, node* root);
void compile_number(compiler* self, node* root, program* prog,
int integer_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);
}
else if (ast->type == NODE_TYPE)
{
return cstatic_new_type(self, TY_TYPE);
}
else if (ast->type == NODE_ARRAY)
{
assert(ast->children.size > 0);

View File

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

View File

@ -4,7 +4,7 @@
#define NODE_TYPE(G) \
G(NODE_PROG), \
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_EQ), G(NODE_NE), \
G(NODE_ASSERT), \

View File

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

View File

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

View File

@ -10,6 +10,7 @@
G(TY_FLOAT), \
G(TY_STRING), \
G(TY_ARRAY), \
G(TY_TYPE), \
G(TY_TYPE_COUNT)
enum Types {
@ -20,13 +21,19 @@ extern char const* TypesStr[];
typedef struct type {
int base_type;
struct type* array_type;
struct {
size_t size;
size_t capacity;
struct type** data;
} sub_types;
} type;
void type_init(type* self, int base_type);
void type_init_array(type* self, type* array_type);
void type_free(type* self);
void type_add_sub_type(type* self, type* rhs);
type* type_new_clone(type* self);
int type_equals(type* self, type* rhs);
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);
}
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)
{
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
&& self->val.string != NULL)
{
@ -92,6 +111,11 @@ value* value_new_clone(value* self)
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)
{
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;
}
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)
{
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:
return snprintf(buffer, size, "%d",
self->val.integer);
case TY_TYPE:
return type_str(self->val.type_val, buffer, size);
default: {
fprintf(stderr, "E: unknown value");
fprintf(stderr, "E: cannot stringify unknown value");
exit(-1);
}
}

View File

@ -14,6 +14,7 @@ typedef struct {
float real_float;
char* string;
array* array_val;
type* type_val;
} val;
} 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_string(value* self, char* string, 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);

View File

@ -634,7 +634,7 @@ void vm_acat(vm* self)
array* rhs_arr = rhs->val.array_val;
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++)
{
@ -668,7 +668,7 @@ void vm_amul(vm* self)
int count = rhs->val.integer;
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 (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>