Compare commits
2 Commits
c2e9880c99
...
7f5b5486c0
Author | SHA1 | Date |
---|---|---|
bog | 7f5b5486c0 | |
bog | 73cd8e0c4a |
|
@ -30,6 +30,12 @@ void array_free(array* self)
|
|||
free(self->type); self->type = NULL;
|
||||
}
|
||||
|
||||
struct value* array_deref_copy(array* self, size_t index)
|
||||
{
|
||||
assert(index < self->children.size);
|
||||
return (struct value*) value_new_clone((value*)self->children.data[index]);
|
||||
}
|
||||
|
||||
void array_push(array* self, struct value* element)
|
||||
{
|
||||
assert(self);
|
||||
|
|
|
@ -18,6 +18,7 @@ typedef struct {
|
|||
void array_init(array* self, type* elements_type);
|
||||
void array_free(array* self);
|
||||
|
||||
struct value* array_deref_copy(array* self, size_t index);
|
||||
void array_push(array* self, struct value* element);
|
||||
|
||||
size_t array_str(array* self, char* buffer, size_t size);
|
||||
|
|
|
@ -17,13 +17,18 @@ void compile_node(compiler* self, node* root, program* prog)
|
|||
assert(root);
|
||||
assert(prog);
|
||||
|
||||
if (root->type == NODE_MUL)
|
||||
if (root->type == NODE_INDEX)
|
||||
{
|
||||
compile_children(self, root, prog);
|
||||
program_add_instr(prog, OP_ADEREF, NO_PARAM);
|
||||
}
|
||||
else if (root->type == NODE_MUL)
|
||||
{
|
||||
cstatic cs;
|
||||
cstatic_init(&cs);
|
||||
|
||||
int lhs = cstatic_resolve(&cs, root->children.data[0]);
|
||||
int rhs = cstatic_resolve(&cs, root->children.data[1]);
|
||||
int lhs = cstatic_resolve_base_type(&cs, root->children.data[0]);
|
||||
int rhs = cstatic_resolve_base_type(&cs, root->children.data[1]);
|
||||
|
||||
cstatic_free(&cs);
|
||||
|
||||
|
@ -49,8 +54,8 @@ void compile_node(compiler* self, node* root, program* prog)
|
|||
cstatic cs;
|
||||
cstatic_init(&cs);
|
||||
|
||||
int lhs = cstatic_resolve(&cs, root->children.data[0]);
|
||||
int rhs = cstatic_resolve(&cs, root->children.data[1]);
|
||||
int lhs = cstatic_resolve_base_type(&cs, root->children.data[0]);
|
||||
int rhs = cstatic_resolve_base_type(&cs, root->children.data[1]);
|
||||
|
||||
cstatic_free(&cs);
|
||||
|
||||
|
@ -195,7 +200,7 @@ void compile_number(compiler* self, node* root, program* prog,
|
|||
cstatic cs;
|
||||
cstatic_init(&cs);
|
||||
|
||||
int ty = cstatic_resolve(&cs, root);
|
||||
int ty = cstatic_resolve_base_type(&cs, root);
|
||||
|
||||
switch (ty)
|
||||
{
|
||||
|
|
239
src/cstatic.c
239
src/cstatic.c
|
@ -11,74 +11,115 @@ void cstatic_free(cstatic* self)
|
|||
assert(self);
|
||||
}
|
||||
|
||||
int cstatic_resolve(cstatic* self, node* ast)
|
||||
type* cstatic_new_type(cstatic* self, int base_type)
|
||||
{
|
||||
assert(self);
|
||||
type* ty = malloc(sizeof(type));
|
||||
type_init(ty, base_type);
|
||||
return ty;
|
||||
}
|
||||
|
||||
int cstatic_resolve_base_type(cstatic* self, node* ast)
|
||||
{
|
||||
assert(self);
|
||||
type* ty = cstatic_resolve_new(self, ast);
|
||||
int res = ty->base_type;
|
||||
type_free(ty);
|
||||
free(ty);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
type* cstatic_resolve_new(cstatic* self, node* ast)
|
||||
{
|
||||
assert(self);
|
||||
assert(ast);
|
||||
|
||||
if (ast->type == NODE_MUL)
|
||||
{
|
||||
int lhs = cstatic_resolve(self, ast->children.data[0]);
|
||||
int rhs = cstatic_resolve(self, ast->children.data[1]);
|
||||
int lhs = cstatic_resolve_base_type(self, ast->children.data[0]);
|
||||
int rhs = cstatic_resolve_base_type(self, ast->children.data[1]);
|
||||
|
||||
if (lhs == TY_STRING || rhs == TY_STRING)
|
||||
{
|
||||
return TY_STRING;
|
||||
return cstatic_new_type(self, TY_STRING);
|
||||
}
|
||||
}
|
||||
|
||||
if (ast->type == NODE_INTEGER)
|
||||
if (ast->type == NODE_INDEX)
|
||||
{
|
||||
return TY_INTEGER;
|
||||
// find inner type using first array element
|
||||
size_t dim = ast->children.data[1]->children.size;
|
||||
node* iter = ast->children.data[0];
|
||||
|
||||
for (size_t i=0; i<dim; i++)
|
||||
{
|
||||
iter = iter->children.data[0];
|
||||
}
|
||||
|
||||
return cstatic_resolve_new(self, iter);
|
||||
}
|
||||
else if (ast->type == NODE_INTEGER)
|
||||
{
|
||||
return cstatic_new_type(self, TY_INTEGER);
|
||||
}
|
||||
else if (ast->type == NODE_FLOAT)
|
||||
{
|
||||
return TY_FLOAT;
|
||||
return cstatic_new_type(self, TY_FLOAT);
|
||||
}
|
||||
|
||||
else if (ast->type == NODE_ADD)
|
||||
{
|
||||
int lhs = cstatic_resolve(self, ast->children.data[0]);
|
||||
int rhs = cstatic_resolve(self, ast->children.data[1]);
|
||||
int lhs = cstatic_resolve_base_type(self, ast->children.data[0]);
|
||||
int rhs = cstatic_resolve_base_type(self, ast->children.data[1]);
|
||||
|
||||
if (lhs == TY_STRING && rhs == TY_STRING)
|
||||
{
|
||||
return TY_STRING;
|
||||
return cstatic_new_type(self, TY_STRING);
|
||||
}
|
||||
|
||||
return lhs;
|
||||
return cstatic_new_type(self, lhs);
|
||||
}
|
||||
|
||||
else if (ast->type == NODE_STRING)
|
||||
{
|
||||
return TY_STRING;
|
||||
return cstatic_new_type(self, TY_STRING);
|
||||
}
|
||||
|
||||
else if (ast->type == NODE_ARRAY)
|
||||
{
|
||||
return TY_ARRAY;
|
||||
assert(ast->children.size > 0);
|
||||
type* child = cstatic_resolve_new(self, ast->children.data[0]);
|
||||
|
||||
type* ty = malloc(sizeof(type));
|
||||
type_init_array(ty, child);
|
||||
|
||||
type_free(child);
|
||||
free(child);
|
||||
|
||||
return ty;
|
||||
}
|
||||
|
||||
else if (ast->type == NODE_BOOLEAN
|
||||
|| ast->type == NODE_EQ
|
||||
|| ast->type == NODE_NE)
|
||||
{
|
||||
return TY_BOOLEAN;
|
||||
return cstatic_new_type(self, TY_BOOLEAN);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (size_t i=0; i<ast->children.size; i++)
|
||||
{
|
||||
int ty = cstatic_resolve(self, ast->children.data[i]);
|
||||
type* ty = cstatic_resolve_new(self, ast->children.data[i]);
|
||||
|
||||
if (ty != TY_NIL)
|
||||
if (ty != NULL)
|
||||
{
|
||||
return ty;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return TY_NIL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int cstatic_check(cstatic* self, node* ast, char* msg, size_t size)
|
||||
|
@ -98,11 +139,55 @@ int cstatic_check(cstatic* self, node* ast, char* msg, size_t size)
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
// Arrays
|
||||
if (ast->type == NODE_ARRAY)
|
||||
if (ast->type == NODE_INDEX)
|
||||
{
|
||||
// check dimension
|
||||
size_t dim = ast->children.data[1]->children.size;
|
||||
size_t real_dim = 0;
|
||||
|
||||
node* iter = ast->children.data[0];
|
||||
while (iter->type == NODE_ARRAY)
|
||||
{
|
||||
iter = iter->children.data[0];
|
||||
real_dim++;
|
||||
}
|
||||
|
||||
if (real_dim != dim)
|
||||
{
|
||||
snprintf(msg, size,
|
||||
"E: array dimension mismatch:"
|
||||
" expected '%ld', got '%ld'.",
|
||||
real_dim, dim);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// check that all indexes are integers
|
||||
for (size_t i=0; i<dim; i++)
|
||||
{
|
||||
int status = cstatic_check_type_base(
|
||||
self,
|
||||
ast->children.data[1]->children.data[i],
|
||||
msg,
|
||||
size,
|
||||
TY_INTEGER,
|
||||
TYPE_END
|
||||
);
|
||||
|
||||
if (!status)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
else if (ast->type == NODE_ARRAY)
|
||||
{
|
||||
assert(ast->children.size > 0);
|
||||
int ty = cstatic_resolve(self, ast->children.data[0]);
|
||||
type* ty = cstatic_resolve_new(self, ast->children.data[0]);
|
||||
|
||||
for (size_t i=1; i<ast->children.size; i++)
|
||||
{
|
||||
|
@ -112,23 +197,28 @@ int cstatic_check(cstatic* self, node* ast, char* msg, size_t size)
|
|||
msg,
|
||||
size,
|
||||
ty,
|
||||
TYPE_END
|
||||
NULL
|
||||
);
|
||||
|
||||
if (!status)
|
||||
{
|
||||
type_free(ty);
|
||||
free(ty);
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
type_free(ty);
|
||||
free(ty);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
// String Operations
|
||||
if (ast->type == NODE_ADD)
|
||||
{
|
||||
int lhs = cstatic_resolve(self, ast->children.data[0]);
|
||||
int rhs = cstatic_resolve(self, ast->children.data[1]);
|
||||
int lhs = cstatic_resolve_base_type(self, ast->children.data[0]);
|
||||
int rhs = cstatic_resolve_base_type(self, ast->children.data[1]);
|
||||
|
||||
|
||||
if (lhs == rhs && lhs == TY_STRING)
|
||||
|
@ -139,8 +229,8 @@ int cstatic_check(cstatic* self, node* ast, char* msg, size_t size)
|
|||
|
||||
if (ast->type == NODE_MUL)
|
||||
{
|
||||
int lhs = cstatic_resolve(self, ast->children.data[0]);
|
||||
int rhs = cstatic_resolve(self, ast->children.data[1]);
|
||||
int lhs = cstatic_resolve_base_type(self, ast->children.data[0]);
|
||||
int rhs = cstatic_resolve_base_type(self, ast->children.data[1]);
|
||||
|
||||
if ((lhs == TY_STRING && rhs == TY_INTEGER)
|
||||
|| (lhs == TY_INTEGER && rhs == TY_STRING))
|
||||
|
@ -169,7 +259,7 @@ int cstatic_check(cstatic* self, node* ast, char* msg, size_t size)
|
|||
else if (ast->type == NODE_ASSERT
|
||||
|| ast->type == NODE_NOT)
|
||||
{
|
||||
int status = cstatic_check_type(self,
|
||||
int status = cstatic_check_type_base(self,
|
||||
ast->children.data[0],
|
||||
msg,
|
||||
size,
|
||||
|
@ -197,7 +287,7 @@ int cstatic_check(cstatic* self, node* ast, char* msg, size_t size)
|
|||
return status;
|
||||
}
|
||||
|
||||
status = cstatic_check_type(self,
|
||||
status = cstatic_check_type_base(self,
|
||||
ast->children.data[0],
|
||||
msg,
|
||||
size,
|
||||
|
@ -213,7 +303,7 @@ int cstatic_check(cstatic* self, node* ast, char* msg, size_t size)
|
|||
else if (ast->type == NODE_UADD
|
||||
|| ast->type == NODE_USUB)
|
||||
{
|
||||
int status = cstatic_check_type(self,
|
||||
int status = cstatic_check_type_base(self,
|
||||
ast->children.data[0],
|
||||
msg,
|
||||
size,
|
||||
|
@ -245,7 +335,7 @@ int cstatic_check(cstatic* self, node* ast, char* msg, size_t size)
|
|||
return status;
|
||||
}
|
||||
|
||||
status = cstatic_check_type(self,
|
||||
status = cstatic_check_type_base(self,
|
||||
ast->children.data[0],
|
||||
msg,
|
||||
size,
|
||||
|
@ -262,7 +352,68 @@ int cstatic_check(cstatic* self, node* ast, char* msg, size_t size)
|
|||
}
|
||||
|
||||
int cstatic_check_type(cstatic* self, node* lhs,
|
||||
char* msg, size_t size, int types, ...)
|
||||
char* msg, size_t size, type* types, ...)
|
||||
{
|
||||
assert(self);
|
||||
assert(lhs);
|
||||
char aze[512];
|
||||
node_str(lhs, aze, 512);
|
||||
|
||||
va_list args;
|
||||
va_start(args, types);
|
||||
type* rhs = types;
|
||||
|
||||
type* left = cstatic_resolve_new(self, lhs);
|
||||
|
||||
type* all_types[TY_TYPE_COUNT];
|
||||
|
||||
for (int i=0; i<TY_TYPE_COUNT; i++)
|
||||
{
|
||||
all_types[i] = NULL;
|
||||
}
|
||||
|
||||
size_t i = 0;
|
||||
|
||||
while (rhs != NULL)
|
||||
{
|
||||
all_types[i] = rhs;
|
||||
|
||||
if (type_equals(left, rhs))
|
||||
{
|
||||
va_end(args);
|
||||
type_free(left);
|
||||
free(left);
|
||||
return 1;
|
||||
}
|
||||
|
||||
rhs = va_arg(args, type*);
|
||||
i++;
|
||||
}
|
||||
|
||||
va_end(args);
|
||||
|
||||
size_t sz = snprintf(msg, size, "E(%d): type mismatch, got '", lhs->lineno);
|
||||
sz += type_str(left, msg + sz, size - sz);
|
||||
|
||||
sz += snprintf(msg + sz, size - sz, "', expected: \n");
|
||||
|
||||
size_t j = 0;
|
||||
|
||||
while (all_types[j] != NULL)
|
||||
{
|
||||
sz += snprintf(msg + sz, size - sz, "\t - ");
|
||||
sz += type_str(all_types[j], msg + sz, size - sz);
|
||||
sz += snprintf(msg + sz, size - sz, "\n");
|
||||
j++;
|
||||
}
|
||||
|
||||
type_free(left);
|
||||
free(left);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cstatic_check_type_base(cstatic* self, node* lhs,
|
||||
char* msg, size_t size, int types, ...)
|
||||
{
|
||||
assert(self);
|
||||
assert(lhs);
|
||||
|
@ -273,7 +424,7 @@ int cstatic_check_type(cstatic* self, node* lhs,
|
|||
va_start(args, types);
|
||||
int rhs = types;
|
||||
|
||||
int left = cstatic_resolve(self, lhs);
|
||||
int left = cstatic_resolve_base_type(self, lhs);
|
||||
|
||||
int all_types[TY_TYPE_COUNT];
|
||||
memset(all_types, TYPE_END, TY_TYPE_COUNT * sizeof(int));
|
||||
|
@ -297,7 +448,7 @@ int cstatic_check_type(cstatic* self, node* lhs,
|
|||
|
||||
size_t sz = snprintf(msg, size, "E(%d): type mismatch, got '%s', ",
|
||||
lhs->lineno,
|
||||
TypesStr[left]);
|
||||
TypesStr[left] + strlen("TY_"));
|
||||
|
||||
sz += snprintf(msg + sz, size - sz, "expected: \n");
|
||||
|
||||
|
@ -306,7 +457,7 @@ int cstatic_check_type(cstatic* self, node* lhs,
|
|||
while (all_types[j] != TYPE_END)
|
||||
{
|
||||
sz += snprintf(msg + sz, size - sz, "\t '%s'\n",
|
||||
TypesStr[all_types[j]]);
|
||||
TypesStr[all_types[j]] + strlen("TY_"));
|
||||
j++;
|
||||
}
|
||||
|
||||
|
@ -320,17 +471,27 @@ int cstatic_check_same_type(cstatic* self, node* lhs, node* rhs,
|
|||
assert(lhs);
|
||||
assert(rhs);
|
||||
|
||||
int left = cstatic_resolve(self, lhs);
|
||||
int right = cstatic_resolve(self, rhs);
|
||||
type* left = cstatic_resolve_new(self, lhs);
|
||||
type* right = cstatic_resolve_new(self, rhs);
|
||||
|
||||
if (left != right)
|
||||
if (!type_equals(left, right))
|
||||
{
|
||||
snprintf(msg, size, "E(%d): expected '%s', got '%s'.",
|
||||
lhs->lineno,
|
||||
TypesStr[left],
|
||||
TypesStr[right]);
|
||||
size_t sz = 0;
|
||||
|
||||
sz += snprintf(msg + sz, size - sz, "E(%d): expected '", lhs->lineno);
|
||||
sz += type_str(left, msg + sz, size - sz);
|
||||
sz += snprintf(msg + sz, size - sz, "', got '");
|
||||
sz += type_str(right, msg + sz, size - sz);
|
||||
sz += snprintf(msg + sz, size - sz, "'");
|
||||
|
||||
type_free(left); free(left);
|
||||
type_free(right); free(right);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
type_free(left); free(left);
|
||||
type_free(right); free(right);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
#include "commons.h"
|
||||
#include "node.h"
|
||||
#include "type.h"
|
||||
|
||||
#define TYPE_END (-1)
|
||||
|
||||
|
@ -13,11 +14,17 @@ typedef struct {
|
|||
void cstatic_init(cstatic* self);
|
||||
void cstatic_free(cstatic* self);
|
||||
|
||||
int cstatic_resolve(cstatic* self, node* ast);
|
||||
type* cstatic_new_type(cstatic* self, int base_type);
|
||||
int cstatic_resolve_base_type(cstatic* self, node* ast);
|
||||
|
||||
type* cstatic_resolve_new(cstatic* self, node* ast);
|
||||
int cstatic_check(cstatic* self, node* ast, char* msg, size_t size);
|
||||
|
||||
int cstatic_check_type(cstatic* self, node* lhs,
|
||||
char* msg, size_t size, int types, ...);
|
||||
char* msg, size_t size, type* types, ...);
|
||||
|
||||
int cstatic_check_type_base(cstatic* self, node* lhs,
|
||||
char* msg, size_t size, int types, ...);
|
||||
|
||||
int cstatic_check_same_type(cstatic* self, node* lhs, node* rhs,
|
||||
char* msg, size_t size);
|
||||
|
|
|
@ -20,6 +20,7 @@ STRING \"[^"]*\"
|
|||
{WHITESPACES} {}
|
||||
|
||||
"assert" { return ASSERT; }
|
||||
"," { return COMMA; }
|
||||
"+" { return ADD; }
|
||||
"-" { return SUB; }
|
||||
"*" { return MUL; }
|
||||
|
|
|
@ -60,13 +60,15 @@ int main(int argc, char** argv)
|
|||
{
|
||||
size_t const BUF = 1024;
|
||||
char buffer[BUF];
|
||||
|
||||
memset(buffer, 0, BUF);
|
||||
node_str(ast, buffer, BUF);
|
||||
printf("-- ast ---\n%s\n\n", buffer);
|
||||
|
||||
memset(buffer, 0, BUF);
|
||||
program_str(&prog, buffer, BUF);
|
||||
printf("--- program ---\n%s\n", buffer);
|
||||
|
||||
memset(buffer, 0, BUF);
|
||||
vm_str(&v, buffer, BUF);
|
||||
printf("--- stack ---\n%s\n", buffer);
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
G(NODE_ASSERT), \
|
||||
G(NODE_UADD), G(NODE_USUB), G(NODE_ADD), G(NODE_SUB), \
|
||||
G(NODE_MUL), G(NODE_DIV), G(NODE_MOD), G(NODE_POW), \
|
||||
G(NODE_ARRAY)
|
||||
G(NODE_ARRAY), G(NODE_INDEX)
|
||||
|
||||
|
||||
#include "mutils.h"
|
||||
|
|
|
@ -28,7 +28,8 @@
|
|||
G(OP_FUSUB), \
|
||||
G(OP_CAT), \
|
||||
G(OP_SMUL), \
|
||||
G(OP_MKARRAY)
|
||||
G(OP_MKARRAY), \
|
||||
G(OP_ADEREF)
|
||||
|
||||
enum Opcodes {
|
||||
OPCODES(GEN_ENUM)
|
||||
|
|
85
src/parser.y
85
src/parser.y
|
@ -23,7 +23,8 @@
|
|||
|
||||
%left ASSERT
|
||||
%token <str> BOOLEAN INTEGER FLOAT STRING
|
||||
%type <n_children> expr exprs prog;
|
||||
%type <n_children> expr exprs prog array arrays builtins
|
||||
%type <n_children> expr_list
|
||||
%left EQ NE
|
||||
%left AND
|
||||
%left OR
|
||||
|
@ -31,7 +32,7 @@
|
|||
%left MUL DIV MOD
|
||||
%left POW
|
||||
%left NOT
|
||||
%token OPAR CPAR OSQUARE CSQUARE
|
||||
%token OPAR CPAR OSQUARE CSQUARE COMMA
|
||||
|
||||
%%
|
||||
|
||||
|
@ -66,7 +67,36 @@ exprs:
|
|||
|
||||
|
||||
expr:
|
||||
ASSERT expr {
|
||||
// INDEX
|
||||
array array {
|
||||
node *n = malloc(sizeof(node));
|
||||
node_init(n, NODE_INDEX, "", line);
|
||||
size_t const SZ = $1 + $2;
|
||||
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;
|
||||
}
|
||||
|
||||
// EXPRESSIONS
|
||||
| array {
|
||||
$$ = 1;
|
||||
}
|
||||
|
||||
| builtins {
|
||||
$$ = $1;
|
||||
}
|
||||
|
||||
| ASSERT expr {
|
||||
node *n = malloc(sizeof(node));
|
||||
node_init(n, NODE_ASSERT, "", line);
|
||||
node_add_child(n, stack_pop());
|
||||
|
@ -213,27 +243,12 @@ expr:
|
|||
$$ = $2;
|
||||
}
|
||||
|
||||
| OSQUARE exprs CSQUARE {
|
||||
node *n = malloc(sizeof(node));
|
||||
node_init(n, NODE_ARRAY, "", line);
|
||||
|
||||
node* elements[$2];
|
||||
;
|
||||
|
||||
for (size_t i=0; i<$2; i++)
|
||||
{
|
||||
elements[i] = stack_pop();
|
||||
}
|
||||
builtins:
|
||||
|
||||
for (size_t i=0; i<$2; i++)
|
||||
{
|
||||
node_add_child(n, elements[$2 - 1 - i]);
|
||||
}
|
||||
|
||||
stack_push(n);
|
||||
$$ = 1;
|
||||
}
|
||||
|
||||
| STRING {
|
||||
STRING {
|
||||
node* n = malloc(sizeof(node));
|
||||
size_t const SZ = strlen($1);
|
||||
char str[SZ - 2];
|
||||
|
@ -267,6 +282,34 @@ expr:
|
|||
}
|
||||
;
|
||||
|
||||
expr_list:
|
||||
expr { $$ = $1; }
|
||||
| expr_list COMMA expr { $$ = $1 + $3; }
|
||||
;
|
||||
|
||||
array:
|
||||
OSQUARE expr_list CSQUARE {
|
||||
node *n = malloc(sizeof(node));
|
||||
node_init(n, NODE_ARRAY, "", line);
|
||||
|
||||
node* elements[$2];
|
||||
|
||||
for (size_t i=0; i<$2; i++)
|
||||
{
|
||||
elements[i] = stack_pop();
|
||||
}
|
||||
|
||||
for (size_t i=0; i<$2; i++)
|
||||
{
|
||||
node_add_child(n, elements[$2 - 1 - i]);
|
||||
}
|
||||
|
||||
stack_push(n);
|
||||
$$ = 1;
|
||||
}
|
||||
|
||||
;
|
||||
|
||||
%%
|
||||
|
||||
void yyerror(char const* msg)
|
||||
|
|
47
src/type.c
47
src/type.c
|
@ -6,11 +6,26 @@ void type_init(type* self, int base_type)
|
|||
{
|
||||
assert(self);
|
||||
self->base_type = base_type;
|
||||
self->array_type = NULL;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
void type_free(type* self)
|
||||
{
|
||||
assert(self);
|
||||
|
||||
if (self->array_type != NULL)
|
||||
{
|
||||
type_free(self->array_type);
|
||||
free(self->array_type);
|
||||
}
|
||||
}
|
||||
|
||||
type* type_new_clone(type* self)
|
||||
|
@ -20,6 +35,11 @@ type* type_new_clone(type* self)
|
|||
type* clone = malloc(sizeof(type));
|
||||
type_init(clone, self->base_type);
|
||||
|
||||
if (self->array_type)
|
||||
{
|
||||
clone->array_type = type_new_clone(self->array_type);
|
||||
}
|
||||
|
||||
return clone;
|
||||
}
|
||||
|
||||
|
@ -28,11 +48,34 @@ int type_equals(type* self, type* rhs)
|
|||
assert(self);
|
||||
assert(rhs);
|
||||
|
||||
return self->base_type == rhs->base_type;
|
||||
if (self->base_type != rhs->base_type)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (self->base_type == TY_ARRAY)
|
||||
{
|
||||
assert(self->array_type);
|
||||
assert(rhs->array_type);
|
||||
return type_equals(self->array_type, rhs->array_type);
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
||||
}
|
||||
|
||||
size_t type_str(type* self, char* buffer, size_t size)
|
||||
{
|
||||
assert(self);
|
||||
return snprintf(buffer, size, "%s", TypesStr[self->base_type]);
|
||||
size_t sz = snprintf(buffer, size, "%s",
|
||||
TypesStr[self->base_type] + strlen("TY_"));
|
||||
|
||||
if (self->base_type == TY_ARRAY)
|
||||
{
|
||||
sz += snprintf(buffer + sz, size - sz, "<");
|
||||
sz += type_str(self->array_type, buffer + sz, size - sz);
|
||||
sz += snprintf(buffer + sz, size - sz, ">");
|
||||
}
|
||||
|
||||
return sz;
|
||||
}
|
||||
|
|
|
@ -20,9 +20,11 @@ extern char const* TypesStr[];
|
|||
|
||||
typedef struct type {
|
||||
int base_type;
|
||||
struct type* array_type;
|
||||
} type;
|
||||
|
||||
void type_init(type* self, int base_type);
|
||||
void type_init_array(type* self, type* array_type);
|
||||
void type_free(type* self);
|
||||
|
||||
type* type_new_clone(type* self);
|
||||
|
|
|
@ -51,8 +51,9 @@ void value_init_array(value* self, array* arr, int lineno)
|
|||
self->val.array_val = array_new_clone(arr);
|
||||
|
||||
self->lineno = lineno;
|
||||
|
||||
self->type = malloc(sizeof(type));
|
||||
type_init(self->type, TY_ARRAY);
|
||||
type_init_array(self->type, arr->type);
|
||||
}
|
||||
|
||||
void value_free(value* self)
|
||||
|
|
39
src/vm.c
39
src/vm.c
|
@ -70,6 +70,7 @@ void vm_exec(vm* self, program* prog)
|
|||
case OP_CAT: vm_cat(self); break;
|
||||
|
||||
case OP_MKARRAY: vm_mkarray(self, param); break;
|
||||
case OP_ADEREF: vm_aderef(self); break;
|
||||
|
||||
default: {
|
||||
fprintf(stderr, "unknown opcode %s\n",
|
||||
|
@ -568,8 +569,8 @@ void vm_mkarray(vm* self, int param)
|
|||
array_push(arr, (struct value*) elements[i]);
|
||||
}
|
||||
|
||||
|
||||
value_init_array(arr_val, arr, elements[0]->lineno);
|
||||
|
||||
vm_push_value(self, arr_val);
|
||||
|
||||
for (int i=0; i<param; i++)
|
||||
|
@ -583,3 +584,39 @@ void vm_mkarray(vm* self, int param)
|
|||
|
||||
self->pc++;
|
||||
}
|
||||
|
||||
void vm_aderef(vm* self)
|
||||
{
|
||||
assert(self);
|
||||
|
||||
value* idx = vm_pop_value(self);
|
||||
value* arr = vm_pop_value(self);
|
||||
|
||||
array* idx_array = idx->val.array_val;
|
||||
|
||||
value* val = NULL;
|
||||
|
||||
for (size_t i=0; i<idx_array->children.size; i++)
|
||||
{
|
||||
size_t index = ((value*) idx_array->children.data[i])->val.integer;
|
||||
|
||||
val = (value*) array_deref_copy(
|
||||
arr->val.array_val,
|
||||
index);
|
||||
|
||||
if (val->type->base_type == TY_ARRAY)
|
||||
{
|
||||
value_free(arr);
|
||||
free(arr);
|
||||
arr = val;
|
||||
}
|
||||
}
|
||||
assert(val);
|
||||
|
||||
vm_push_value(self, val);
|
||||
|
||||
value_free(idx); free(idx);
|
||||
value_free(arr); free(arr);
|
||||
|
||||
self->pc++;
|
||||
}
|
||||
|
|
2
src/vm.h
2
src/vm.h
|
@ -54,4 +54,6 @@ void vm_smul(vm* self);
|
|||
void vm_cat(vm* self);
|
||||
void vm_mkarray(vm* self, int param);
|
||||
|
||||
void vm_aderef(vm* self);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,2 +1,8 @@
|
|||
[]
|
||||
[1 2 3 "4"]
|
||||
[1, 2, 3, "4"]
|
||||
[ [0, 1], ["0", "1"] ]
|
||||
[1, 2, 3]["a"]
|
||||
[1, 2, 3][false]
|
||||
[1, 2, 3][3.14]
|
||||
[1, 2, 3][ [0, 1] ]
|
||||
[1, 2, 3][0, 0]
|
||||
|
|
|
@ -1,11 +1,23 @@
|
|||
assert [1 - 2 3] == [-1 3]
|
||||
assert [1 -2 3] == [1 -2 3]
|
||||
assert [1, 2, 3] == [1, 2, 3]
|
||||
assert ["a", "b", "c"] == ["a", "b", "c"]
|
||||
|
||||
assert [1, 2, 3] != [7, 2, 3]
|
||||
assert [1, 2, 3] != [1, 2, 3, 4]
|
||||
|
||||
assert ["a", "b", "c"] != ["ac", "b", "c"]
|
||||
assert ["a", "b", "c"] != ["a", "b", "c", "d"]
|
||||
|
||||
assert 3 == [3, 8, 9][0]
|
||||
assert 8 == [3, 8, 9][1]
|
||||
assert 9 == [3, 8, 9][2]
|
||||
|
||||
assert "8" == ["3", "8", "9"][2 - 1]
|
||||
|
||||
assert 7 == [[4, 6], [9, 2, 7], [3, 3, 2]][1, 2]
|
||||
assert 9 == [[4, 6], [9, 2, 7], [3, 3, 2]][[2, 9, 1][2], 0]
|
||||
|
||||
|
||||
|
||||
|
||||
assert [1 2 3] == [1 2 3]
|
||||
assert ["a" "b" "c"] == ["a" "b" "c"]
|
||||
|
||||
assert [1 2 3] != [7 2 3]
|
||||
assert [1 2 3] != [1 2 3 4]
|
||||
|
||||
assert ["a" "b" "c"] != ["ac" "b" "c"]
|
||||
assert ["a" "b" "c"] != ["a" "b" "c" "d"]
|
||||
|
|
Loading…
Reference in New Issue