ADD: type literals.

main
bog 2023-08-24 23:28:45 +02:00
parent 7a4e71bf14
commit 0b44732961
10 changed files with 210 additions and 25 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

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

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

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>