Add print statement
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
if 1 == 2: {
|
let a = 5
|
||||||
let a = 1
|
let b = 5
|
||||||
} else {
|
|
||||||
let b =
|
if a == b: print "a and b are the same\n"
|
||||||
}
|
else print "they are not the same!\n"
|
||||||
@@ -433,6 +433,14 @@ void assemble_node(Assembler *a, Node *node)
|
|||||||
{
|
{
|
||||||
switch (node->type) {
|
switch (node->type) {
|
||||||
|
|
||||||
|
case NODE_PRINT:
|
||||||
|
{
|
||||||
|
assemble_node(a, node->left);
|
||||||
|
append_u8(&a->out, OPCODE_PRINT);
|
||||||
|
append_u8(&a->out, OPCODE_POP);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case NODE_FUNC_DECL:
|
case NODE_FUNC_DECL:
|
||||||
{
|
{
|
||||||
append_u8(&a->out, OPCODE_JUMP);
|
append_u8(&a->out, OPCODE_JUMP);
|
||||||
@@ -1130,6 +1138,10 @@ void print_program(Program p)
|
|||||||
case OPCODE_SELECT:
|
case OPCODE_SELECT:
|
||||||
printf("SELECT");
|
printf("SELECT");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case OPCODE_PRINT:
|
||||||
|
printf("PRINT");
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("\n");
|
printf("\n");
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ enum {
|
|||||||
OPCODE_INSERT1 = 0x18,
|
OPCODE_INSERT1 = 0x18,
|
||||||
OPCODE_INSERT2 = 0x19,
|
OPCODE_INSERT2 = 0x19,
|
||||||
OPCODE_SELECT = 0x20,
|
OPCODE_SELECT = 0x20,
|
||||||
|
OPCODE_PRINT = 0x24,
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
|||||||
@@ -18,8 +18,10 @@ typedef struct {
|
|||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#define LLU "llu"
|
#define LLU "llu"
|
||||||
|
#define LLD "lld"
|
||||||
#else
|
#else
|
||||||
#define LLU "lu"
|
#define LLU "lu"
|
||||||
|
#define LLD "ld"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define S(X) (String) { (X), (int) sizeof(X)-1 }
|
#define S(X) (String) { (X), (int) sizeof(X)-1 }
|
||||||
|
|||||||
+27
-17
@@ -141,7 +141,7 @@ Type type_of(Value v)
|
|||||||
// 001 true
|
// 001 true
|
||||||
// 010 false
|
// 010 false
|
||||||
// 011 int
|
// 011 int
|
||||||
// 100 string
|
// 100
|
||||||
// 101
|
// 101
|
||||||
// 110 error
|
// 110 error
|
||||||
// 111 pointer
|
// 111 pointer
|
||||||
@@ -151,10 +151,10 @@ Type type_of(Value v)
|
|||||||
case 1: return TYPE_BOOL;
|
case 1: return TYPE_BOOL;
|
||||||
case 2: return TYPE_BOOL;
|
case 2: return TYPE_BOOL;
|
||||||
case 3: return TYPE_INT;
|
case 3: return TYPE_INT;
|
||||||
case 4: return TYPE_STRING;
|
case 4: break;
|
||||||
case 5: break;
|
case 5: break;
|
||||||
case 6: return TYPE_ERROR;
|
case 6: return TYPE_ERROR;
|
||||||
case 7: return *(Type*) v;
|
case 7: return *(Type*) ((uintptr_t) v & ~(uintptr_t) 7);
|
||||||
}
|
}
|
||||||
|
|
||||||
return TYPE_ERROR;
|
return TYPE_ERROR;
|
||||||
@@ -175,12 +175,9 @@ float get_float(Value v)
|
|||||||
return p->raw;
|
return p->raw;
|
||||||
}
|
}
|
||||||
|
|
||||||
String get_str(Value *v)
|
String get_str(Value v)
|
||||||
{
|
{
|
||||||
if ((*v & 7) == 6)
|
StringValue *p = (StringValue*) (v & ~(uintptr_t) 7);
|
||||||
return (String) { (char*) v, strnlen((char*) v, 7) };
|
|
||||||
|
|
||||||
StringValue *p = (StringValue*) (*v & ~(uintptr_t) 7);
|
|
||||||
return (String) { p->data, p->len };
|
return (String) { p->data, p->len };
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -197,7 +194,7 @@ ArrayValue *get_array(Value v)
|
|||||||
Value make_int(Eval *e, int64_t x)
|
Value make_int(Eval *e, int64_t x)
|
||||||
{
|
{
|
||||||
if (x <= (int64_t) (1ULL << 60)-1 && x >= (int64_t) -(1ULL << 60))
|
if (x <= (int64_t) (1ULL << 60)-1 && x >= (int64_t) -(1ULL << 60))
|
||||||
return ((Value) x >> 3) | 3;
|
return ((Value) x << 3) | 3;
|
||||||
|
|
||||||
IntValue *v = alloc(e->a, (int) sizeof(IntValue), _Alignof(IntValue));
|
IntValue *v = alloc(e->a, (int) sizeof(IntValue), _Alignof(IntValue));
|
||||||
if (v == NULL) {
|
if (v == NULL) {
|
||||||
@@ -229,18 +226,13 @@ Value make_float(Eval *e, float x)
|
|||||||
|
|
||||||
Value make_str(Eval *e, String x)
|
Value make_str(Eval *e, String x)
|
||||||
{
|
{
|
||||||
if (x.len < 8) {
|
StringValue *v = alloc(e->a, (int) sizeof(StringValue) + x.len, 8);
|
||||||
Value v = 0;
|
|
||||||
memcpy(&v, x.ptr, x.len);
|
|
||||||
return v | 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
StringValue *v = alloc(e->a, (int) sizeof(StringValue) + x.len, _Alignof(StringValue));
|
|
||||||
if (v == NULL) {
|
if (v == NULL) {
|
||||||
eval_report(e, "Out of memory");
|
eval_report(e, "Out of memory");
|
||||||
return VALUE_ERROR;
|
return VALUE_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
v->type = TYPE_STRING;
|
||||||
v->len = x.len;
|
v->len = x.len;
|
||||||
memcpy(v->data, x.ptr, x.len);
|
memcpy(v->data, x.ptr, x.len);
|
||||||
|
|
||||||
@@ -399,7 +391,7 @@ b32 valeq(Value a, Value b)
|
|||||||
return false; // TODO
|
return false; // TODO
|
||||||
|
|
||||||
case TYPE_STRING:
|
case TYPE_STRING:
|
||||||
return streq(get_str(&a), get_str(&b));
|
return streq(get_str(a), get_str(b));
|
||||||
|
|
||||||
case TYPE_ERROR:
|
case TYPE_ERROR:
|
||||||
return true;
|
return true;
|
||||||
@@ -1081,6 +1073,24 @@ int step(Eval *e)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case OPCODE_PRINT:
|
||||||
|
{
|
||||||
|
Value v = e->eval_stack[e->eval_depth-1];
|
||||||
|
|
||||||
|
switch (type_of(v)) {
|
||||||
|
case TYPE_NONE : printf("none"); break;
|
||||||
|
case TYPE_BOOL : printf(v == VALUE_TRUE ? "true" : "false"); break;
|
||||||
|
case TYPE_INT : printf("%" LLD, get_int(v)); break;
|
||||||
|
case TYPE_FLOAT : printf("%lf", get_float(v)); break;
|
||||||
|
case TYPE_MAP : printf("map"); break;
|
||||||
|
case TYPE_ARRAY : printf("array"); break;
|
||||||
|
case TYPE_STRING: printf("%.*s", get_str(v).len, get_str(v).ptr); break;
|
||||||
|
case TYPE_ERROR : printf("error"); break;
|
||||||
|
}
|
||||||
|
fflush(stdout);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
eval_report(e, "Invalid opcode (offset %d)", e->off-1);
|
eval_report(e, "Invalid opcode (offset %d)", e->off-1);
|
||||||
return -1;
|
return -1;
|
||||||
|
|||||||
+3
-3
@@ -25,8 +25,8 @@ int main(void)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
print_node(parse_result.node);
|
//print_node(parse_result.node);
|
||||||
printf("\n");
|
//printf("\n");
|
||||||
|
|
||||||
AssembleResult assemble_result = assemble(parse_result.node, &a, err, COUNT(err));
|
AssembleResult assemble_result = assemble(parse_result.node, &a, err, COUNT(err));
|
||||||
if (assemble_result.errlen) {
|
if (assemble_result.errlen) {
|
||||||
@@ -34,7 +34,7 @@ int main(void)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
print_program(assemble_result.program);
|
//print_program(assemble_result.program);
|
||||||
|
|
||||||
ret = eval(assemble_result.program, &a, err, COUNT(err));
|
ret = eval(assemble_result.program, &a, err, COUNT(err));
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
|
|||||||
+31
@@ -23,6 +23,7 @@ typedef enum {
|
|||||||
TOKEN_KWORD_IN,
|
TOKEN_KWORD_IN,
|
||||||
TOKEN_KWORD_FUN,
|
TOKEN_KWORD_FUN,
|
||||||
TOKEN_KWORD_LET,
|
TOKEN_KWORD_LET,
|
||||||
|
TOKEN_KWORD_PRINT,
|
||||||
TOKEN_VALUE_FLOAT,
|
TOKEN_VALUE_FLOAT,
|
||||||
TOKEN_VALUE_INT,
|
TOKEN_VALUE_INT,
|
||||||
TOKEN_VALUE_STR,
|
TOKEN_VALUE_STR,
|
||||||
@@ -106,6 +107,7 @@ String tok2str(Token token, char *buf, int max)
|
|||||||
case TOKEN_KWORD_IN: return S("in");
|
case TOKEN_KWORD_IN: return S("in");
|
||||||
case TOKEN_KWORD_FUN: return S("fun");
|
case TOKEN_KWORD_FUN: return S("fun");
|
||||||
case TOKEN_KWORD_LET: return S("let");
|
case TOKEN_KWORD_LET: return S("let");
|
||||||
|
case TOKEN_KWORD_PRINT: return S("print");
|
||||||
|
|
||||||
case TOKEN_VALUE_FLOAT:
|
case TOKEN_VALUE_FLOAT:
|
||||||
{
|
{
|
||||||
@@ -227,6 +229,7 @@ Token next_token(Parser *p)
|
|||||||
if (streq(kword, S("in"))) return (Token) { .type=TOKEN_KWORD_IN };
|
if (streq(kword, S("in"))) return (Token) { .type=TOKEN_KWORD_IN };
|
||||||
if (streq(kword, S("fun"))) return (Token) { .type=TOKEN_KWORD_FUN };
|
if (streq(kword, S("fun"))) return (Token) { .type=TOKEN_KWORD_FUN };
|
||||||
if (streq(kword, S("let"))) return (Token) { .type=TOKEN_KWORD_LET };
|
if (streq(kword, S("let"))) return (Token) { .type=TOKEN_KWORD_LET };
|
||||||
|
if (streq(kword, S("print"))) return (Token) { .type=TOKEN_KWORD_PRINT };
|
||||||
return (Token) { .type=TOKEN_IDENT, .sval=kword };
|
return (Token) { .type=TOKEN_IDENT, .sval=kword };
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1413,6 +1416,31 @@ Node *parse_var_decl(Parser *p, int opflags)
|
|||||||
return parent;
|
return parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Node *parse_print_stmt(Parser *p, int opflags)
|
||||||
|
{
|
||||||
|
int start = p->s.cur;
|
||||||
|
|
||||||
|
Token t = next_token(p);
|
||||||
|
if (t.type != TOKEN_KWORD_PRINT) {
|
||||||
|
parser_report(p, "Missing keyword 'print' at the start of a print statement");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
Node *arg = parse_expr(p, opflags);
|
||||||
|
if (arg == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
Node *parent = alloc_node(p);
|
||||||
|
if (parent == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
parent->type = NODE_PRINT;
|
||||||
|
parent->text = (String) { p->s.src + start, p->s.cur - start };
|
||||||
|
parent->left = arg;
|
||||||
|
|
||||||
|
return parent;
|
||||||
|
}
|
||||||
|
|
||||||
Node *parse_stmt(Parser *p, int opflags)
|
Node *parse_stmt(Parser *p, int opflags)
|
||||||
{
|
{
|
||||||
Scanner saved = p->s;
|
Scanner saved = p->s;
|
||||||
@@ -1421,6 +1449,9 @@ Node *parse_stmt(Parser *p, int opflags)
|
|||||||
|
|
||||||
switch (t.type) {
|
switch (t.type) {
|
||||||
|
|
||||||
|
case TOKEN_KWORD_PRINT:
|
||||||
|
return parse_print_stmt(p, opflags);
|
||||||
|
|
||||||
case TOKEN_KWORD_FUN:
|
case TOKEN_KWORD_FUN:
|
||||||
return parse_func_decl(p, opflags);
|
return parse_func_decl(p, opflags);
|
||||||
|
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ typedef enum {
|
|||||||
NODE_FUNC_ARG,
|
NODE_FUNC_ARG,
|
||||||
NODE_FUNC_CALL,
|
NODE_FUNC_CALL,
|
||||||
NODE_VAR_DECL,
|
NODE_VAR_DECL,
|
||||||
|
NODE_PRINT,
|
||||||
NODE_BLOCK,
|
NODE_BLOCK,
|
||||||
NODE_IFELSE,
|
NODE_IFELSE,
|
||||||
NODE_FOR,
|
NODE_FOR,
|
||||||
|
|||||||
Reference in New Issue
Block a user