From 71968d2b59903d1f61b31bfa2b9fb86293ccaad4 Mon Sep 17 00:00:00 2001 From: Francesco Cozzuto Date: Sun, 3 Aug 2025 22:33:44 +0200 Subject: [PATCH] Add print statement --- main.wl | 10 +++++----- src/assemble.c | 12 ++++++++++++ src/assemble.h | 1 + src/basic.h | 2 ++ src/eval.c | 44 +++++++++++++++++++++++++++----------------- src/main.c | 6 +++--- src/parse.c | 31 +++++++++++++++++++++++++++++++ src/parse.h | 1 + 8 files changed, 82 insertions(+), 25 deletions(-) diff --git a/main.wl b/main.wl index 1e67c99..871badc 100644 --- a/main.wl +++ b/main.wl @@ -1,5 +1,5 @@ -if 1 == 2: { - let a = 1 -} else { - let b = -} \ No newline at end of file +let a = 5 +let b = 5 + +if a == b: print "a and b are the same\n" +else print "they are not the same!\n" \ No newline at end of file diff --git a/src/assemble.c b/src/assemble.c index f185134..dbe6a84 100644 --- a/src/assemble.c +++ b/src/assemble.c @@ -433,6 +433,14 @@ void assemble_node(Assembler *a, Node *node) { 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: { append_u8(&a->out, OPCODE_JUMP); @@ -1130,6 +1138,10 @@ void print_program(Program p) case OPCODE_SELECT: printf("SELECT"); break; + + case OPCODE_PRINT: + printf("PRINT"); + break; } printf("\n"); diff --git a/src/assemble.h b/src/assemble.h index 18fd38e..d971cca 100644 --- a/src/assemble.h +++ b/src/assemble.h @@ -34,6 +34,7 @@ enum { OPCODE_INSERT1 = 0x18, OPCODE_INSERT2 = 0x19, OPCODE_SELECT = 0x20, + OPCODE_PRINT = 0x24, }; typedef struct { diff --git a/src/basic.h b/src/basic.h index 1c88178..6bfa112 100644 --- a/src/basic.h +++ b/src/basic.h @@ -18,8 +18,10 @@ typedef struct { #ifdef _WIN32 #define LLU "llu" +#define LLD "lld" #else #define LLU "lu" +#define LLD "ld" #endif #define S(X) (String) { (X), (int) sizeof(X)-1 } diff --git a/src/eval.c b/src/eval.c index 5c12368..17b64f8 100644 --- a/src/eval.c +++ b/src/eval.c @@ -141,7 +141,7 @@ Type type_of(Value v) // 001 true // 010 false // 011 int - // 100 string + // 100 // 101 // 110 error // 111 pointer @@ -151,10 +151,10 @@ Type type_of(Value v) case 1: return TYPE_BOOL; case 2: return TYPE_BOOL; case 3: return TYPE_INT; - case 4: return TYPE_STRING; + case 4: break; case 5: break; case 6: return TYPE_ERROR; - case 7: return *(Type*) v; + case 7: return *(Type*) ((uintptr_t) v & ~(uintptr_t) 7); } return TYPE_ERROR; @@ -175,12 +175,9 @@ float get_float(Value v) return p->raw; } -String get_str(Value *v) +String get_str(Value v) { - if ((*v & 7) == 6) - return (String) { (char*) v, strnlen((char*) v, 7) }; - - StringValue *p = (StringValue*) (*v & ~(uintptr_t) 7); + StringValue *p = (StringValue*) (v & ~(uintptr_t) 7); return (String) { p->data, p->len }; } @@ -197,7 +194,7 @@ ArrayValue *get_array(Value v) Value make_int(Eval *e, int64_t x) { 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)); if (v == NULL) { @@ -229,18 +226,13 @@ Value make_float(Eval *e, float x) Value make_str(Eval *e, String x) { - if (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)); + StringValue *v = alloc(e->a, (int) sizeof(StringValue) + x.len, 8); if (v == NULL) { eval_report(e, "Out of memory"); return VALUE_ERROR; } + v->type = TYPE_STRING; v->len = x.len; memcpy(v->data, x.ptr, x.len); @@ -399,7 +391,7 @@ b32 valeq(Value a, Value b) return false; // TODO case TYPE_STRING: - return streq(get_str(&a), get_str(&b)); + return streq(get_str(a), get_str(b)); case TYPE_ERROR: return true; @@ -1081,6 +1073,24 @@ int step(Eval *e) } 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: eval_report(e, "Invalid opcode (offset %d)", e->off-1); return -1; diff --git a/src/main.c b/src/main.c index 177339f..c9c40ec 100644 --- a/src/main.c +++ b/src/main.c @@ -25,8 +25,8 @@ int main(void) return -1; } - print_node(parse_result.node); - printf("\n"); + //print_node(parse_result.node); + //printf("\n"); AssembleResult assemble_result = assemble(parse_result.node, &a, err, COUNT(err)); if (assemble_result.errlen) { @@ -34,7 +34,7 @@ int main(void) return -1; } - print_program(assemble_result.program); + //print_program(assemble_result.program); ret = eval(assemble_result.program, &a, err, COUNT(err)); if (ret < 0) { diff --git a/src/parse.c b/src/parse.c index b6dd31a..44fac6b 100644 --- a/src/parse.c +++ b/src/parse.c @@ -23,6 +23,7 @@ typedef enum { TOKEN_KWORD_IN, TOKEN_KWORD_FUN, TOKEN_KWORD_LET, + TOKEN_KWORD_PRINT, TOKEN_VALUE_FLOAT, TOKEN_VALUE_INT, 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_FUN: return S("fun"); case TOKEN_KWORD_LET: return S("let"); + case TOKEN_KWORD_PRINT: return S("print"); 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("fun"))) return (Token) { .type=TOKEN_KWORD_FUN }; 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 }; } @@ -1413,6 +1416,31 @@ Node *parse_var_decl(Parser *p, int opflags) 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) { Scanner saved = p->s; @@ -1421,6 +1449,9 @@ Node *parse_stmt(Parser *p, int opflags) switch (t.type) { + case TOKEN_KWORD_PRINT: + return parse_print_stmt(p, opflags); + case TOKEN_KWORD_FUN: return parse_func_decl(p, opflags); diff --git a/src/parse.h b/src/parse.h index c76ee08..dcf7991 100644 --- a/src/parse.h +++ b/src/parse.h @@ -12,6 +12,7 @@ typedef enum { NODE_FUNC_ARG, NODE_FUNC_CALL, NODE_VAR_DECL, + NODE_PRINT, NODE_BLOCK, NODE_IFELSE, NODE_FOR,