typedef struct {
enum {
- VAL_I8, VAL_I16, VAL_I32, VAL_I64, VAL_REAL, VAL_STRING
+ VAL_I8, VAL_I16, VAL_I32, VAL_I64, VAL_BOOL, VAL_REAL, VAL_STRING, VAL_NIL
} type;
union {
long long integer;
Tok tok;
Symbol globals;
Symbol locals;
- int valstack_idx;
- Value valstack[1024];
+ int validx;
+ Value vals[1024];
} Parser;
void lexfile(Parser* ctx, char* path);
/* Code Generation
*****************************************************************************/
-void codegen_int(Parser* p, int val);
+void codegen_print(Parser* p);
+void codegen_int(Parser* p, long long val);
void codegen_real(Parser* p, double val);
void codegen_string(Parser* p, char* val);
void codegen_bool(Parser* p, int val);
#include "cerise.h"
+#include <limits.h>
+#include <assert.h>
-void codegen_int(Parser* p, int val)
+static Value* peek_val(Parser* p)
{
- (void)p;
- printf("%d ", val);
+ return &(p->vals[p->validx-1]);
+}
+
+static void push_int(Parser* p, int type, long long val)
+{
+ Value* v = &(p->vals[p->validx++]);
+ v->type = type;
+ v->value.integer = val;
+}
+
+static void push_float(Parser* p, double val)
+{
+ Value* v = &(p->vals[p->validx++]);
+ v->type = VAL_REAL;
+ v->value.floating = val;
+}
+
+static void push_string(Parser* p, char* val)
+{
+ Value* v = &(p->vals[p->validx++]);
+ v->type = VAL_STRING;
+ v->value.text = val;
+}
+
+static void push_nil(Parser* p)
+{
+ Value* v = &(p->vals[p->validx++]);
+ v->type = VAL_NIL;
+ v->value.integer = 0;
+}
+
+static void pop_val(Parser* p, Value* val)
+{
+ p->validx--;
+ *val = p->vals[p->validx];
+}
+
+
+static int is_int(Value* val)
+{
+ return (val->type <= VAL_I64);
+}
+
+
+
+
+void codegen_print(Parser* p)
+{
+ printf("DUMP: [ ");
+ for (int i = 0; i < p->validx; i++)
+ {
+ switch (p->vals[i].type)
+ {
+ case VAL_I8:
+ case VAL_I16:
+ case VAL_I32:
+ case VAL_I64:
+ case VAL_BOOL:
+ printf("%lld ", p->vals[i].value.integer);
+ break;
+ case VAL_REAL:
+ printf("%f ", p->vals[i].value.floating);
+ break;
+ case VAL_STRING:
+ printf("%s ", p->vals[i].value.text);
+ break;
+ case VAL_NIL:
+ printf("nil ");
+ break;
+ }
+ }
+ printf("]\n");
+}
+
+void codegen_int(Parser* p, long long val)
+{
+ printf("%lld ", val);
+
+ if (CHAR_MIN <= val && CHAR_MAX >= val)
+ {
+ push_int(p, VAL_I8, val);
+ }
+ else if (SHRT_MIN <= val && SHRT_MAX >= val)
+ {
+ push_int(p, VAL_I16, val);
+ }
+ else if (INT_MIN <= val && INT_MAX >= val)
+ {
+ push_int(p, VAL_I32, val);
+ }
+ else if (LONG_MIN <= val && LONG_MAX >= val)
+ {
+ push_int(p, VAL_I64, val);
+ }
+ else
+ {
+// printf("unknown unary operator %d\n", val);
+ }
}
void codegen_real(Parser* p, double val)
{
- (void)p;
printf("%f ", val);
+ push_float(p, val);
}
void codegen_string(Parser* p, char* val)
{
- (void)p;
printf("\"%s\" ", val);
+ push_string(p, val);
}
void codegen_bool(Parser* p, int val)
{
(void)p;
printf("%s ", val ? "true" : "false");
+ push_int(p, VAL_BOOL, val);
}
void codegen_nil(Parser* p)
{
(void)p;
printf("nil ");
+ push_nil(p);
}
void codegen_unop(Parser* p, int val)
{
(void)p;
if (val < 256) { printf("(%c) ", val); } else { printf("(%d) ", val); }
+ Value* v = peek_val(p);
+ switch (val)
+ {
+ case '+':
+ if (is_int(v))
+ {
+ v->value.integer = +v->value.integer;
+ }
+ else if (v->type == VAL_REAL)
+ {
+ v->value.floating = +v->value.floating;
+ }
+ else
+ {
+ assert(false);
+ }
+ break;
+
+ case '-':
+ if (is_int(v))
+ {
+ v->value.integer = -v->value.integer;
+ }
+ else if (v->type == VAL_REAL)
+ {
+ v->value.floating = -v->value.floating;
+ }
+ else
+ {
+ assert(false);
+ }
+ break;
+
+ case NOT:
+ if (v->type == VAL_BOOL)
+ {
+ v->value.integer = !v->value.integer;
+ }
+ else
+ {
+ assert(false);
+ }
+ break;
+
+ default:
+ printf("unknown unary operator %d\n", val);
+ break;
+ }
}
void codegen_binop(Parser* p, int val)