#include "bitset.h" #include "builtins.h" #include "error.h" #include "eval.h" #include "intern.h" #include "lexer.h" #include "scope.h" #include "source.h" #include "stdio.h" #include "syntax.h" #include "error.h" #include "value.h" #include #define generate_comp_binop(op_name, op_expr) \ value_t * op_name(gc_t *gc, value_t **args, size_t num_args) { \ if (num_args != 2) \ return NULL; \ if (args[0] == NULL || args[1] == NULL) return NULL; \ if (args[0]->tag == VALUE_INT && args[1]->tag == VALUE_INT) { \ long lhs = args[0]->as.integer; \ long rhs = args[1]->as.integer; \ int result = op_expr; \ return(value_alloc_bool(gc,result)); \ } else if ( (args[0]->tag == VALUE_FLOAT || args[0]->tag == VALUE_INT) \ && (args[1]->tag == VALUE_FLOAT || args[1]->tag == VALUE_INT) ) { \ double lhs = (args[0]->tag == VALUE_FLOAT) ? args[0]->as.floating : (double)args[0]->as.integer; \ double rhs = (args[0]->tag == VALUE_FLOAT) ? args[1]->as.floating : (double)args[1]->as.integer; \ int result = op_expr; \ return(value_alloc_bool(gc,result)); \ } else return NULL; \ } bool primop_eq_impl(value_t *arg0, value_t *arg1) { if (arg0 == NULL || arg1 == NULL) return true; if (arg0->tag == VALUE_INT && arg1->tag == VALUE_INT) { return (arg0->as.integer == arg1->as.integer); } else if ( (arg0->tag == VALUE_FLOAT || arg0->tag == VALUE_INT) && (arg1->tag == VALUE_FLOAT || arg1->tag == VALUE_INT) ) { double lhs = (arg0->tag == VALUE_FLOAT) ? arg0->as.floating : (double)arg0->as.integer; double rhs = (arg0->tag == VALUE_FLOAT) ? arg1->as.floating : (double)arg1->as.integer; return (lhs==rhs); } else if ( arg0->tag == VALUE_STRING && arg1->tag == VALUE_STRING) { return (strcmp(arg0->as.string.string, arg1->as.string.string) == 0); } else if ( arg0->tag == VALUE_BUILTIN && arg1->tag == VALUE_BUILTIN) { return (arg0->as.builtin == arg1->as.builtin); } else if ( arg0->tag == VALUE_CLOSURE && arg1->tag == VALUE_CLOSURE) { return (arg0 == arg1); } else if ( arg0->tag == VALUE_CONSTRUCTOR && arg1->tag == VALUE_CONSTRUCTOR) { if (arg0->as.constructor.name == arg1->as.constructor.name && arg0->as.constructor.num_args == arg1->as.constructor.num_args) { for (int i = 0; i < arg0->as.constructor.num_args; i++) { if (!primop_eq_impl(arg0->as.constructor.args[i],arg1->as.constructor.args[i])) return false; } return true; } } } value_t * primop_eq(gc_t *gc, value_t **args, size_t num_args) { if (num_args != 2) return NULL; return value_alloc_bool(gc, primop_eq_impl(args[0], args[1])); } value_t * primop_noteq(gc_t *gc, value_t **args, size_t num_args) { if (num_args != 2) return NULL; return value_alloc_bool(gc, !primop_eq_impl(args[0], args[1])); } #define generate_arith_binop(op_name, op_expr) \ value_t * op_name(gc_t *gc, value_t **args, size_t num_args) { \ if (num_args != 2) \ return NULL; \ if (args[0] == NULL || args[1] == NULL) return NULL; \ if (args[0]->tag == VALUE_INT && args[1]->tag == VALUE_INT) { \ long lhs = args[0]->as.integer; \ long rhs = args[1]->as.integer; \ long result = op_expr; \ return value_alloc_int(gc, result); \ } else if ( (args[0]->tag == VALUE_FLOAT || args[0]->tag == VALUE_INT) \ && (args[1]->tag == VALUE_FLOAT || args[1]->tag == VALUE_INT) ) { \ double lhs = (args[0]->tag == VALUE_FLOAT) ? args[0]->as.floating : (double)args[0]->as.integer; \ double rhs = (args[0]->tag == VALUE_FLOAT) ? args[1]->as.floating : (double)args[1]->as.integer; \ return value_alloc_float(gc, op_expr); \ } else return NULL; \ } generate_arith_binop(primop_plus, lhs + rhs) generate_arith_binop(primop_minus, lhs - rhs) generate_arith_binop(primop_mult, lhs * rhs) generate_arith_binop(primop_div, lhs / rhs) generate_arith_binop(primop_mod, (long)lhs % (long)rhs) generate_arith_binop(primop_idiv, (long)lhs / (long)rhs) generate_comp_binop(primop_greater, lhs > rhs) generate_comp_binop(primop_lesser, lhs < rhs) generate_comp_binop(primop_greatereq, lhs >= rhs) generate_comp_binop(primop_lessereq, lhs <= rhs) int main(int argc, char**argv) { source_t *source = source_alloc_from_file("test.hito"); lexer_t *lexer = lexer_alloc(source); token_t tok; intern_table_t *table = intern_table_alloc(); builtins_t *builtins = builtins_alloc(); builtins_add(builtins, intern(table,"+"),primop_plus); builtins_add(builtins, intern(table,"-"),primop_minus); builtins_add(builtins, intern(table,"mod"),primop_mod); builtins_add(builtins, intern(table,"/"),primop_div); builtins_add(builtins, intern(table,"div"),primop_idiv); builtins_add(builtins, intern(table,"*"),primop_mult); builtins_add(builtins, intern(table,">"),primop_greater); builtins_add(builtins, intern(table,"<"),primop_lesser); builtins_add(builtins, intern(table,">="),primop_greatereq); builtins_add(builtins, intern(table,"<="),primop_lessereq); builtins_add(builtins, intern(table,"="),primop_eq); builtins_add(builtins, intern(table,"/="),primop_noteq); expr_t *expr = syntax_parse_expr(lexer, builtins, table); printf("%p\n", expr); if (expr == NULL) return 1; syntax_dump_expr(expr); printf("\n"); gc_t *gc = gc_alloc(); value_t *v = eval(expr, gc); value_debug_dump(v); printf("\n"); }