Compare commits
2 Commits
1a2edd01f1
...
0b44732961
Author | SHA1 | Date |
---|---|---|
bog | 0b44732961 | |
bog | 7a4e71bf14 |
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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; }
|
||||
|
|
|
@ -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), \
|
||||
|
|
98
src/parser.y
98
src/parser.y
|
@ -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,21 +115,8 @@ 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{
|
||||
node *n = malloc(sizeof(node));
|
||||
|
@ -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];
|
||||
|
|
73
src/type.c
73
src/type.c
|
@ -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;
|
||||
|
@ -53,15 +79,21 @@ 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)
|
||||
|
@ -70,10 +102,23 @@ size_t type_str(type* self, char* buffer, size_t size)
|
|||
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, ">");
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
34
src/value.c
34
src/value.c
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
4
src/vm.c
4
src/vm.c
|
@ -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++)
|
||||
|
|
|
@ -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>
|
Loading…
Reference in New Issue