from tokens import * import sys from collections import namedtuple FuncImpl = namedtuple("FuncImpl", ("func", "impl")) STD = {} DEBUG = True USER = {} def _get_debug(): return DEBUG def std_exit(status=None): out = 0 if status is None else status.value sys.exit(out) return NebBool(True) # this should never be reached def std_print(arg): print(arg.value) #return [] # TODO this should return empty list return NebBool(True) def std_debug_on(): global DEBUG DEBUG = True return NebBool(True) def std_debug_off(): global DEBUG DEBUG = False return NebBool(True) # math def std_add(arg1, arg2): res = arg1.value + arg2.value if isinstance(arg1, NebFloat) or isinstance(arg2, NebFloat): return NebFloat(res) else: return NebInt(res) def std_subtract(arg1, arg2): res = arg1.value - arg2.value if isinstance(arg1, NebFloat) or isinstance(arg2, NebFloat): return NebFloat(res) else: return NebInt(res) def std_multiply(arg1, arg2): res = arg1.value * arg2.value if isinstance(arg1, NebFloat) or isinstance(arg2, NebFloat): return NebFloat(res) else: return NebInt(res) # strings def std_concat(arg1, arg2): return NebString(f"{arg1.value}{arg2.value}") # flow control def std_if(cond, t_branch, f_branch): if cond.value: ret = evaluate_expression(t_branch) else: ret = evaluate_expression(f_branch) return ret # type validation def std_is_string(arg): if isinstance(arg, NebString): return NebBool(True) else: return NebBool(False) def evaluate_expression(expr): if not expr.symbol.name in STD: raise Exception(f"no such symbol: {expr.symbol.name}") this_func = STD[expr.symbol.name] # try to match the signature validated = 0 in_sig = expr.args for value in this_func: sig = value.func.args validated = 0 if len(sig) != len(in_sig): continue for idx in range(len(sig)): if isinstance(in_sig[idx], sig[idx]): validated += 1 if validated == len(sig): print(f"{value.func.args}") ret = value.impl(*(expr.args)) return ret # evaluate inner expressions, if possible/necessary for idx, arg in enumerate(expr.args): if isinstance(arg, NebExpression): expr.args[idx] = evaluate_expression(arg) return evaluate_expression(expr) raise Exception(f"'{expr.symbol.name}' called with unknown signature: '{expr.in_sig()}'") def build_std(): print_string = FuncImpl(NebFunction("print", [NebString], NebString), std_print) STD["print"] = [print_string] exit_ = FuncImpl(NebFunction("exit", [], NebBool), std_exit) exit_int = FuncImpl(NebFunction("exit", [NebInt], NebBool), std_exit) STD["exit"] = [exit_, exit_int] debug_on = FuncImpl(NebFunction("debug-on", [], NebBool), std_debug_on) STD["debug-on"] = [debug_on] debug_off = FuncImpl(NebFunction("debug-off", [], NebBool), std_debug_off) STD["debug-off"] = [debug_off] # arithmetic add = FuncImpl(NebFunction("+", [NebNumber, NebNumber], NebNumber), std_add) STD["+"] = [add] subtract = FuncImpl(NebFunction("-", [NebNumber, NebNumber], NebNumber), std_subtract) STD["-"] = [subtract] multiply = FuncImpl(NebFunction("*", [NebNumber, NebNumber], NebNumber), std_multiply) STD["*"] = [multiply] # strings concat_string_string = FuncImpl(NebFunction("concat", [NebString, NebString], NebString), std_concat) STD["concat"] = [concat_string_string] # flow control if_bool_expr_expr = FuncImpl(NebFunction("if", [NebBool, NebExpression, NebExpression], NebAny), std_if) STD["if"] = [if_bool_expr_expr] # type checking is_string = FuncImpl(NebFunction("string?", [NebAny], NebBool), std_is_string) STD["string?"] = [is_string] build_std()