ADD: array literals.
parent
6013d65776
commit
c2e9880c99
|
@ -40,7 +40,10 @@ executable(
|
||||||
'src/utils.c',
|
'src/utils.c',
|
||||||
'src/opcodes.c',
|
'src/opcodes.c',
|
||||||
'src/program.c',
|
'src/program.c',
|
||||||
|
|
||||||
'src/value.c',
|
'src/value.c',
|
||||||
|
'src/array.c',
|
||||||
|
|
||||||
'src/type.c',
|
'src/type.c',
|
||||||
'src/compiler.c',
|
'src/compiler.c',
|
||||||
'src/cstatic.c',
|
'src/cstatic.c',
|
||||||
|
|
|
@ -0,0 +1,112 @@
|
||||||
|
#include "array.h"
|
||||||
|
#include "value.h"
|
||||||
|
|
||||||
|
void array_init(array* self, type* elements_type)
|
||||||
|
{
|
||||||
|
assert(self);
|
||||||
|
self->type = type_new_clone(elements_type);
|
||||||
|
self->children.size = 0;
|
||||||
|
self->children.capacity = 1;
|
||||||
|
self->children.data = malloc(sizeof(struct value*)
|
||||||
|
* self->children.capacity);
|
||||||
|
}
|
||||||
|
|
||||||
|
void array_free(array* self)
|
||||||
|
{
|
||||||
|
assert(self);
|
||||||
|
|
||||||
|
for (size_t i=0; i<self->children.size; i++)
|
||||||
|
{
|
||||||
|
value_free((value*) self->children.data[i]);
|
||||||
|
free(self->children.data[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(self->children.data);
|
||||||
|
self->children.data = NULL;
|
||||||
|
self->children.size = 0;
|
||||||
|
self->children.capacity = 0;
|
||||||
|
|
||||||
|
type_free(self->type);
|
||||||
|
free(self->type); self->type = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void array_push(array* self, struct value* element)
|
||||||
|
{
|
||||||
|
assert(self);
|
||||||
|
assert(element);
|
||||||
|
|
||||||
|
if (self->children.size >= self->children.capacity)
|
||||||
|
{
|
||||||
|
self->children.capacity *= 2;
|
||||||
|
self->children.data = realloc(
|
||||||
|
self->children.data,
|
||||||
|
sizeof(struct value*)
|
||||||
|
* self->children.capacity
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
self->children.data[self->children.size] =
|
||||||
|
(struct value*) value_new_clone((value*) element);
|
||||||
|
self->children.size++;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t array_str(array* self, char* buffer, size_t size)
|
||||||
|
{
|
||||||
|
assert(self);
|
||||||
|
|
||||||
|
size_t sz = 0;
|
||||||
|
|
||||||
|
sz += snprintf(buffer + sz, size - sz, "[");
|
||||||
|
|
||||||
|
for (size_t i=0; i<self->children.size; i++)
|
||||||
|
{
|
||||||
|
if (i > 0)
|
||||||
|
{
|
||||||
|
sz += snprintf(buffer + sz, size - sz, " ");
|
||||||
|
}
|
||||||
|
|
||||||
|
sz += value_str((value*)self->children.data[i],
|
||||||
|
buffer + sz, size - sz);
|
||||||
|
}
|
||||||
|
|
||||||
|
sz += snprintf(buffer + sz, size - sz, "]");
|
||||||
|
|
||||||
|
return sz;
|
||||||
|
}
|
||||||
|
|
||||||
|
int array_equals(array* self, array* rhs)
|
||||||
|
{
|
||||||
|
assert(self);
|
||||||
|
assert(rhs);
|
||||||
|
|
||||||
|
if (self->children.size != rhs->children.size)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t i=0; i<self->children.size; i++)
|
||||||
|
{
|
||||||
|
if (!value_equals(
|
||||||
|
(value*) self->children.data[i],
|
||||||
|
(value*) rhs->children.data[i]
|
||||||
|
))
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
array* array_new_clone(array* self)
|
||||||
|
{
|
||||||
|
array* clone = malloc(sizeof(array));
|
||||||
|
array_init(clone, self->type);
|
||||||
|
|
||||||
|
for (size_t i=0; i<self->children.size; i++)
|
||||||
|
{
|
||||||
|
array_push(clone, self->children.data[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return clone;
|
||||||
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
#ifndef ARRAY_H
|
||||||
|
#define ARRAY_H
|
||||||
|
|
||||||
|
#include "commons.h"
|
||||||
|
#include "type.h"
|
||||||
|
|
||||||
|
struct value;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
type* type;
|
||||||
|
struct {
|
||||||
|
size_t size;
|
||||||
|
size_t capacity;
|
||||||
|
struct value** data;
|
||||||
|
} children;
|
||||||
|
} array;
|
||||||
|
|
||||||
|
void array_init(array* self, type* elements_type);
|
||||||
|
void array_free(array* self);
|
||||||
|
|
||||||
|
void array_push(array* self, struct value* element);
|
||||||
|
|
||||||
|
size_t array_str(array* self, char* buffer, size_t size);
|
||||||
|
int array_equals(array* self, array* rhs);
|
||||||
|
array* array_new_clone(array* self);
|
||||||
|
|
||||||
|
#endif
|
|
@ -163,6 +163,11 @@ void compile_node(compiler* self, node* root, program* prog)
|
||||||
compile_children(self, root, prog);
|
compile_children(self, root, prog);
|
||||||
program_add_instr(prog, OP_NOT, NO_PARAM);
|
program_add_instr(prog, OP_NOT, NO_PARAM);
|
||||||
}
|
}
|
||||||
|
else if (root->type == NODE_ARRAY)
|
||||||
|
{
|
||||||
|
compile_children(self, root, prog);
|
||||||
|
program_add_instr(prog, OP_MKARRAY, root->children.size);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
compile_children(self, root, prog);
|
compile_children(self, root, prog);
|
||||||
|
|
|
@ -54,6 +54,11 @@ int cstatic_resolve(cstatic* self, node* ast)
|
||||||
return TY_STRING;
|
return TY_STRING;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
else if (ast->type == NODE_ARRAY)
|
||||||
|
{
|
||||||
|
return TY_ARRAY;
|
||||||
|
}
|
||||||
|
|
||||||
else if (ast->type == NODE_BOOLEAN
|
else if (ast->type == NODE_BOOLEAN
|
||||||
|| ast->type == NODE_EQ
|
|| ast->type == NODE_EQ
|
||||||
|| ast->type == NODE_NE)
|
|| ast->type == NODE_NE)
|
||||||
|
@ -93,6 +98,31 @@ int cstatic_check(cstatic* self, node* ast, char* msg, size_t size)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
// Arrays
|
||||||
|
if (ast->type == NODE_ARRAY)
|
||||||
|
{
|
||||||
|
assert(ast->children.size > 0);
|
||||||
|
int ty = cstatic_resolve(self, ast->children.data[0]);
|
||||||
|
|
||||||
|
for (size_t i=1; i<ast->children.size; i++)
|
||||||
|
{
|
||||||
|
int status = cstatic_check_type(
|
||||||
|
self,
|
||||||
|
ast->children.data[i],
|
||||||
|
msg,
|
||||||
|
size,
|
||||||
|
ty,
|
||||||
|
TYPE_END
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!status)
|
||||||
|
{
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
// String Operations
|
// String Operations
|
||||||
if (ast->type == NODE_ADD)
|
if (ast->type == NODE_ADD)
|
||||||
|
|
|
@ -12,11 +12,11 @@ WHITESPACES [ \t]+
|
||||||
BOOLEAN true|false
|
BOOLEAN true|false
|
||||||
INTEGER -?[0-9]+
|
INTEGER -?[0-9]+
|
||||||
FLOAT -?[0-9]+\.[0-9]+
|
FLOAT -?[0-9]+\.[0-9]+
|
||||||
STRING \"[^\"]*\"
|
STRING \"[^"]*\"
|
||||||
|
|
||||||
%%
|
%%
|
||||||
"\n" { line++; }
|
|
||||||
{COMMENT} {}
|
{COMMENT} {}
|
||||||
|
"\n" { line++; }
|
||||||
{WHITESPACES} {}
|
{WHITESPACES} {}
|
||||||
|
|
||||||
"assert" { return ASSERT; }
|
"assert" { return ASSERT; }
|
||||||
|
@ -34,6 +34,8 @@ STRING \"[^\"]*\"
|
||||||
"!" { return NOT; }
|
"!" { return NOT; }
|
||||||
"(" { return OPAR; }
|
"(" { return OPAR; }
|
||||||
")" { return CPAR; }
|
")" { return CPAR; }
|
||||||
|
"[" { return OSQUARE; }
|
||||||
|
"]" { return CSQUARE; }
|
||||||
|
|
||||||
{BOOLEAN} {
|
{BOOLEAN} {
|
||||||
yylval.str = yytext;
|
yylval.str = yytext;
|
||||||
|
|
|
@ -22,10 +22,6 @@ int main(int argc, char** argv)
|
||||||
yyin = stdin;
|
yyin = stdin;
|
||||||
}
|
}
|
||||||
|
|
||||||
node* n = malloc(sizeof(node));
|
|
||||||
node_init(n, NODE_PROG, "", 1);
|
|
||||||
stack_push(n);
|
|
||||||
|
|
||||||
yyparse();
|
yyparse();
|
||||||
|
|
||||||
ast = stack_pop();
|
ast = stack_pop();
|
||||||
|
|
|
@ -9,7 +9,8 @@
|
||||||
G(NODE_EQ), G(NODE_NE), \
|
G(NODE_EQ), G(NODE_NE), \
|
||||||
G(NODE_ASSERT), \
|
G(NODE_ASSERT), \
|
||||||
G(NODE_UADD), G(NODE_USUB), G(NODE_ADD), G(NODE_SUB), \
|
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_MUL), G(NODE_DIV), G(NODE_MOD), G(NODE_POW), \
|
||||||
|
G(NODE_ARRAY)
|
||||||
|
|
||||||
|
|
||||||
#include "mutils.h"
|
#include "mutils.h"
|
||||||
|
|
|
@ -27,7 +27,8 @@
|
||||||
G(OP_FUADD), \
|
G(OP_FUADD), \
|
||||||
G(OP_FUSUB), \
|
G(OP_FUSUB), \
|
||||||
G(OP_CAT), \
|
G(OP_CAT), \
|
||||||
G(OP_SMUL)
|
G(OP_SMUL), \
|
||||||
|
G(OP_MKARRAY)
|
||||||
|
|
||||||
enum Opcodes {
|
enum Opcodes {
|
||||||
OPCODES(GEN_ENUM)
|
OPCODES(GEN_ENUM)
|
||||||
|
|
179
src/parser.y
179
src/parser.y
|
@ -18,11 +18,12 @@
|
||||||
|
|
||||||
%union {
|
%union {
|
||||||
char* str;
|
char* str;
|
||||||
void* node_val;
|
size_t n_children;
|
||||||
};
|
};
|
||||||
|
|
||||||
%left ASSERT
|
%left ASSERT
|
||||||
%token <str> BOOLEAN INTEGER FLOAT STRING
|
%token <str> BOOLEAN INTEGER FLOAT STRING
|
||||||
|
%type <n_children> expr exprs prog;
|
||||||
%left EQ NE
|
%left EQ NE
|
||||||
%left AND
|
%left AND
|
||||||
%left OR
|
%left OR
|
||||||
|
@ -30,26 +31,37 @@
|
||||||
%left MUL DIV MOD
|
%left MUL DIV MOD
|
||||||
%left POW
|
%left POW
|
||||||
%left NOT
|
%left NOT
|
||||||
%type <node_val> expr;
|
%token OPAR CPAR OSQUARE CSQUARE
|
||||||
%token OPAR CPAR
|
|
||||||
|
|
||||||
%%
|
%%
|
||||||
|
|
||||||
prog:
|
prog:
|
||||||
| exprs {
|
{
|
||||||
|
node* n = malloc(sizeof(node));
|
||||||
|
node_init(n, NODE_PROG, "", line);
|
||||||
|
stack_push(n);
|
||||||
|
$$ = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
| exprs {
|
||||||
|
node* n = malloc(sizeof(node));
|
||||||
|
node_init(n, NODE_PROG, "", line);
|
||||||
|
|
||||||
|
for (size_t i=0; i<$1; i++)
|
||||||
|
{
|
||||||
|
node_add_child(n, stack_pop());
|
||||||
|
}
|
||||||
|
|
||||||
|
stack_push(n);
|
||||||
|
|
||||||
|
$$ = $1;
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
exprs:
|
exprs:
|
||||||
exprs expr {
|
exprs expr { $$ = $1 + $2; }
|
||||||
node* parent = stack_top();
|
|
||||||
node_add_child(parent, $2);
|
|
||||||
}
|
|
||||||
|
|
||||||
| expr {
|
| expr { $$ = $1; }
|
||||||
node* parent = stack_top();
|
|
||||||
node_add_child(parent, $1);
|
|
||||||
}
|
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|
||||||
|
@ -57,115 +69,170 @@ expr:
|
||||||
ASSERT expr {
|
ASSERT expr {
|
||||||
node *n = malloc(sizeof(node));
|
node *n = malloc(sizeof(node));
|
||||||
node_init(n, NODE_ASSERT, "", line);
|
node_init(n, NODE_ASSERT, "", line);
|
||||||
node_add_child(n, $2);
|
node_add_child(n, stack_pop());
|
||||||
$$ = n;
|
stack_push(n);
|
||||||
|
|
||||||
|
$$ = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
| ADD expr {
|
| ADD expr {
|
||||||
node *n = malloc(sizeof(node));
|
node *n = malloc(sizeof(node));
|
||||||
node_init(n, NODE_UADD, "", line);
|
node_init(n, NODE_UADD, "", line);
|
||||||
node_add_child(n, $2);
|
node_add_child(n, stack_pop());
|
||||||
$$ = n;
|
stack_push(n);
|
||||||
|
$$ = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
| SUB expr {
|
| SUB expr {
|
||||||
node *n = malloc(sizeof(node));
|
node *n = malloc(sizeof(node));
|
||||||
node_init(n, NODE_USUB, "", line);
|
node_init(n, NODE_USUB, "", line);
|
||||||
node_add_child(n, $2);
|
node_add_child(n, stack_pop());
|
||||||
$$ = n;
|
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_add_child(n, $1);
|
node* rhs = stack_pop();
|
||||||
node_add_child(n, $3);
|
node* lhs = stack_pop();
|
||||||
$$ = n;
|
node_add_child(n, lhs);
|
||||||
|
node_add_child(n, rhs);
|
||||||
|
stack_push(n);
|
||||||
|
$$ = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
| expr SUB expr {
|
| expr SUB expr {
|
||||||
node *n = malloc(sizeof(node));
|
node *n = malloc(sizeof(node));
|
||||||
node_init(n, NODE_SUB, "", line);
|
node_init(n, NODE_SUB, "", line);
|
||||||
node_add_child(n, $1);
|
node* rhs = stack_pop();
|
||||||
node_add_child(n, $3);
|
node* lhs = stack_pop();
|
||||||
$$ = n;
|
node_add_child(n, lhs);
|
||||||
|
node_add_child(n, rhs);
|
||||||
|
stack_push(n);
|
||||||
|
$$ = 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);
|
||||||
node_add_child(n, $1);
|
node* rhs = stack_pop();
|
||||||
node_add_child(n, $3);
|
node* lhs = stack_pop();
|
||||||
$$ = n;
|
node_add_child(n, lhs);
|
||||||
|
node_add_child(n, rhs);
|
||||||
|
stack_push(n);
|
||||||
|
$$ = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
| expr DIV expr {
|
| expr DIV expr {
|
||||||
node *n = malloc(sizeof(node));
|
node *n = malloc(sizeof(node));
|
||||||
node_init(n, NODE_DIV, "", line);
|
node_init(n, NODE_DIV, "", line);
|
||||||
node_add_child(n, $1);
|
node* rhs = stack_pop();
|
||||||
node_add_child(n, $3);
|
node* lhs = stack_pop();
|
||||||
$$ = n;
|
node_add_child(n, lhs);
|
||||||
|
node_add_child(n, rhs);
|
||||||
|
stack_push(n);
|
||||||
|
$$ = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
| expr MOD expr {
|
| expr MOD expr {
|
||||||
node *n = malloc(sizeof(node));
|
node *n = malloc(sizeof(node));
|
||||||
node_init(n, NODE_MOD, "", line);
|
node_init(n, NODE_MOD, "", line);
|
||||||
node_add_child(n, $1);
|
node* rhs = stack_pop();
|
||||||
node_add_child(n, $3);
|
node* lhs = stack_pop();
|
||||||
$$ = n;
|
node_add_child(n, lhs);
|
||||||
|
node_add_child(n, rhs);
|
||||||
|
stack_push(n);
|
||||||
|
$$ = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
| expr POW expr {
|
| expr POW expr {
|
||||||
node *n = malloc(sizeof(node));
|
node *n = malloc(sizeof(node));
|
||||||
node_init(n, NODE_POW, "", line);
|
node_init(n, NODE_POW, "", line);
|
||||||
node_add_child(n, $1);
|
node* rhs = stack_pop();
|
||||||
node_add_child(n, $3);
|
node* lhs = stack_pop();
|
||||||
$$ = n;
|
node_add_child(n, lhs);
|
||||||
|
node_add_child(n, rhs);
|
||||||
|
stack_push(n);
|
||||||
|
$$ = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
| expr EQ expr {
|
| expr EQ expr {
|
||||||
node *n = malloc(sizeof(node));
|
node *n = malloc(sizeof(node));
|
||||||
node_init(n, NODE_EQ, "", line);
|
node_init(n, NODE_EQ, "", line);
|
||||||
node_add_child(n, $1);
|
node* rhs = stack_pop();
|
||||||
node_add_child(n, $3);
|
node* lhs = stack_pop();
|
||||||
$$ = n;
|
node_add_child(n, lhs);
|
||||||
|
node_add_child(n, rhs);
|
||||||
|
stack_push(n);
|
||||||
|
$$ = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
| expr NE expr {
|
| expr NE expr {
|
||||||
node *n = malloc(sizeof(node));
|
node *n = malloc(sizeof(node));
|
||||||
node_init(n, NODE_NE, "", line);
|
node_init(n, NODE_NE, "", line);
|
||||||
node_add_child(n, $1);
|
node* rhs = stack_pop();
|
||||||
node_add_child(n, $3);
|
node* lhs = stack_pop();
|
||||||
$$ = n;
|
node_add_child(n, lhs);
|
||||||
|
node_add_child(n, rhs);
|
||||||
|
stack_push(n);
|
||||||
|
$$ = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
| expr AND expr {
|
| expr AND expr {
|
||||||
node *n = malloc(sizeof(node));
|
node *n = malloc(sizeof(node));
|
||||||
node_init(n, NODE_AND, "", line);
|
node_init(n, NODE_AND, "", line);
|
||||||
node_add_child(n, $1);
|
node* rhs = stack_pop();
|
||||||
node_add_child(n, $3);
|
node* lhs = stack_pop();
|
||||||
$$ = n;
|
node_add_child(n, lhs);
|
||||||
|
node_add_child(n, rhs);
|
||||||
|
stack_push(n);
|
||||||
|
$$ = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
| expr OR expr {
|
| expr OR expr {
|
||||||
node *n = malloc(sizeof(node));
|
node *n = malloc(sizeof(node));
|
||||||
node_init(n, NODE_OR, "", line);
|
node_init(n, NODE_OR, "", line);
|
||||||
node_add_child(n, $1);
|
node* rhs = stack_pop();
|
||||||
node_add_child(n, $3);
|
node* lhs = stack_pop();
|
||||||
$$ = n;
|
node_add_child(n, lhs);
|
||||||
|
node_add_child(n, rhs);
|
||||||
|
stack_push(n);
|
||||||
|
$$ = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
| NOT expr {
|
| NOT expr {
|
||||||
node *n = malloc(sizeof(node));
|
node *n = malloc(sizeof(node));
|
||||||
node_init(n, NODE_NOT, "", line);
|
node_init(n, NODE_NOT, "", line);
|
||||||
node_add_child(n, $2);
|
node_add_child(n, stack_pop());
|
||||||
$$ = n;
|
stack_push(n);
|
||||||
|
$$ = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
| OPAR expr CPAR {
|
| OPAR expr CPAR {
|
||||||
$$ = $2;
|
$$ = $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();
|
||||||
|
}
|
||||||
|
|
||||||
|
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));
|
node* n = malloc(sizeof(node));
|
||||||
size_t const SZ = strlen($1);
|
size_t const SZ = strlen($1);
|
||||||
|
@ -174,25 +241,29 @@ expr:
|
||||||
str[SZ - 2] = '\0';
|
str[SZ - 2] = '\0';
|
||||||
|
|
||||||
node_init(n, NODE_STRING, str, line);
|
node_init(n, NODE_STRING, str, line);
|
||||||
$$ = n;
|
stack_push(n);
|
||||||
|
$$ = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
| BOOLEAN {
|
| BOOLEAN {
|
||||||
node* n = malloc(sizeof(node));
|
node* n = malloc(sizeof(node));
|
||||||
node_init(n, NODE_BOOLEAN, $1, line);
|
node_init(n, NODE_BOOLEAN, $1, line);
|
||||||
$$ = n;
|
stack_push(n);
|
||||||
|
$$ = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
| INTEGER {
|
| INTEGER {
|
||||||
node* n = malloc(sizeof(node));
|
node* n = malloc(sizeof(node));
|
||||||
node_init(n, NODE_INTEGER, $1, line);
|
node_init(n, NODE_INTEGER, $1, line);
|
||||||
$$ = n;
|
stack_push(n);
|
||||||
|
$$ = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
| FLOAT {
|
| FLOAT {
|
||||||
node* n = malloc(sizeof(node));
|
node* n = malloc(sizeof(node));
|
||||||
node_init(n, NODE_FLOAT, $1, line);
|
node_init(n, NODE_FLOAT, $1, line);
|
||||||
$$ = n;
|
stack_push(n);
|
||||||
|
$$ = 1;
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
#include "type.h"
|
#include "type.h"
|
||||||
|
|
||||||
|
|
||||||
char const* TypesStr[] = { TYPES(GEN_STRING) };
|
char const* TypesStr[] = { TYPES(GEN_STRING) };
|
||||||
|
|
||||||
void type_init(type* self, int base_type)
|
void type_init(type* self, int base_type)
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
#ifndef TYPE_H
|
#ifndef TYPE_H
|
||||||
#define TYPE
|
#define TYPE_H
|
||||||
|
|
||||||
#include "commons.h"
|
#include "commons.h"
|
||||||
|
|
||||||
|
@ -9,6 +9,7 @@
|
||||||
G(TY_INTEGER), \
|
G(TY_INTEGER), \
|
||||||
G(TY_FLOAT), \
|
G(TY_FLOAT), \
|
||||||
G(TY_STRING), \
|
G(TY_STRING), \
|
||||||
|
G(TY_ARRAY), \
|
||||||
G(TY_TYPE_COUNT)
|
G(TY_TYPE_COUNT)
|
||||||
|
|
||||||
enum Types {
|
enum Types {
|
||||||
|
|
34
src/value.c
34
src/value.c
|
@ -1,4 +1,5 @@
|
||||||
#include "value.h"
|
#include "value.h"
|
||||||
|
#include "array.h"
|
||||||
|
|
||||||
void value_init_boolean(value* self, int boolean, int lineno)
|
void value_init_boolean(value* self, int boolean, int lineno)
|
||||||
{
|
{
|
||||||
|
@ -42,6 +43,18 @@ void value_init_string(value* self, char* str, int lineno)
|
||||||
type_init(self->type, TY_STRING);
|
type_init(self->type, TY_STRING);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void value_init_array(value* self, array* arr, int lineno)
|
||||||
|
{
|
||||||
|
assert(self);
|
||||||
|
|
||||||
|
|
||||||
|
self->val.array_val = array_new_clone(arr);
|
||||||
|
|
||||||
|
self->lineno = lineno;
|
||||||
|
self->type = malloc(sizeof(type));
|
||||||
|
type_init(self->type, TY_ARRAY);
|
||||||
|
}
|
||||||
|
|
||||||
void value_free(value* self)
|
void value_free(value* self)
|
||||||
{
|
{
|
||||||
assert(self);
|
assert(self);
|
||||||
|
@ -53,6 +66,14 @@ void value_free(value* self)
|
||||||
self->val.string = NULL;
|
self->val.string = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (self->type->base_type == TY_ARRAY
|
||||||
|
&& self->val.array_val != NULL)
|
||||||
|
{
|
||||||
|
array_free(self->val.array_val);
|
||||||
|
free(self->val.array_val);
|
||||||
|
self->val.array_val = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
type_free(self->type);
|
type_free(self->type);
|
||||||
free(self->type);
|
free(self->type);
|
||||||
self->type = NULL;
|
self->type = NULL;
|
||||||
|
@ -70,6 +91,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_ARRAY)
|
||||||
|
{
|
||||||
|
clone->val.array_val = array_new_clone(self->val.array_val);
|
||||||
|
}
|
||||||
|
|
||||||
clone->lineno = self->lineno;
|
clone->lineno = self->lineno;
|
||||||
|
|
||||||
return clone;
|
return clone;
|
||||||
|
@ -106,6 +132,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_ARRAY)
|
||||||
|
{
|
||||||
|
return array_equals(self->val.array_val, rhs->val.array_val);
|
||||||
|
}
|
||||||
|
|
||||||
size_t const SZ = 512;
|
size_t const SZ = 512;
|
||||||
char ty_str[SZ];
|
char ty_str[SZ];
|
||||||
|
|
||||||
|
@ -126,6 +157,9 @@ size_t value_str(value* self, char* buffer, size_t size)
|
||||||
return snprintf(buffer, size, "%s",
|
return snprintf(buffer, size, "%s",
|
||||||
self->val.boolean == 0
|
self->val.boolean == 0
|
||||||
? "false" : "true");
|
? "false" : "true");
|
||||||
|
case TY_ARRAY:
|
||||||
|
return array_str(self->val.array_val, buffer, size);
|
||||||
|
|
||||||
case TY_STRING:
|
case TY_STRING:
|
||||||
return snprintf(buffer, size, "%s",
|
return snprintf(buffer, size, "%s",
|
||||||
self->val.string);
|
self->val.string);
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
#include "commons.h"
|
#include "commons.h"
|
||||||
#include "type.h"
|
#include "type.h"
|
||||||
|
#include "array.h"
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
type* type;
|
type* type;
|
||||||
|
@ -12,6 +13,7 @@ typedef struct {
|
||||||
int integer;
|
int integer;
|
||||||
float real_float;
|
float real_float;
|
||||||
char* string;
|
char* string;
|
||||||
|
array* array_val;
|
||||||
} val;
|
} val;
|
||||||
} value;
|
} value;
|
||||||
|
|
||||||
|
@ -19,6 +21,7 @@ void value_init_boolean(value* self, int boolean, int lineno);
|
||||||
void value_init_integer(value* self, int integer, int lineno);
|
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_free(value* self);
|
void value_free(value* self);
|
||||||
|
|
||||||
|
|
37
src/vm.c
37
src/vm.c
|
@ -69,6 +69,8 @@ void vm_exec(vm* self, program* prog)
|
||||||
case OP_SMUL: vm_smul(self); break;
|
case OP_SMUL: vm_smul(self); break;
|
||||||
case OP_CAT: vm_cat(self); break;
|
case OP_CAT: vm_cat(self); break;
|
||||||
|
|
||||||
|
case OP_MKARRAY: vm_mkarray(self, param); break;
|
||||||
|
|
||||||
default: {
|
default: {
|
||||||
fprintf(stderr, "unknown opcode %s\n",
|
fprintf(stderr, "unknown opcode %s\n",
|
||||||
OpcodesStr[opcode]);
|
OpcodesStr[opcode]);
|
||||||
|
@ -546,3 +548,38 @@ void vm_cat(vm* self)
|
||||||
|
|
||||||
self->pc++;
|
self->pc++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void vm_mkarray(vm* self, int param)
|
||||||
|
{
|
||||||
|
value* elements[param];
|
||||||
|
|
||||||
|
for (int i=0; i<param; i++)
|
||||||
|
{
|
||||||
|
elements[param - 1 - i] = vm_pop_value(self);
|
||||||
|
}
|
||||||
|
|
||||||
|
array* arr = malloc(sizeof(array));
|
||||||
|
array_init(arr, elements[0]->type);
|
||||||
|
|
||||||
|
value* arr_val = malloc(sizeof(value));
|
||||||
|
|
||||||
|
for (int i=0; i<param; i++)
|
||||||
|
{
|
||||||
|
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++)
|
||||||
|
{
|
||||||
|
value_free(elements[i]);
|
||||||
|
free(elements[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
array_free(arr);
|
||||||
|
free(arr);
|
||||||
|
|
||||||
|
self->pc++;
|
||||||
|
}
|
||||||
|
|
1
src/vm.h
1
src/vm.h
|
@ -52,5 +52,6 @@ void vm_assert(vm* self);
|
||||||
|
|
||||||
void vm_smul(vm* self);
|
void vm_smul(vm* self);
|
||||||
void vm_cat(vm* self);
|
void vm_cat(vm* self);
|
||||||
|
void vm_mkarray(vm* self, int param);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
[]
|
||||||
|
[1 2 3 "4"]
|
|
@ -0,0 +1,11 @@
|
||||||
|
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"]
|
Loading…
Reference in New Issue