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=None): if cond.value: if isinstance(t_branch, NebExpression): return evaluate_expression(t_branch) else: return t_branch elif f_branch is not None: if isinstance(t_branch, NebExpression): return evaluate_expression(f_branch) else: return f_branch return NebBool(True) # type validation def std_is_string(arg): if isinstance(arg, NebString): return NebBool(True) else: return NebBool(False) def std_is_int(arg): if isinstance(arg, NebInt): return NebBool(True) else: return NebBool(False) def std_is_float(arg): if isinstance(arg, NebFloat): return NebBool(True) else: return NebBool(False) def std_is_number(arg): if isinstance(arg, NebNumber): return NebBool(True) else: return NebBool(False) def std_is_bool(arg): if isinstance(arg, NebBool): 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): 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_any_any = FuncImpl(NebFunction("if", [NebBool, NebAny, NebAny], NebAny), std_if) if_bool_any = FuncImpl(NebFunction("if", [NebBool, NebAny], NebAny), std_if) STD["if"] = [if_bool_any_any, if_bool_any] # type checking is_string = FuncImpl(NebFunction("string?", [NebAny], NebBool), std_is_string) STD["string?"] = [is_string] is_int = FuncImpl(NebFunction("string?", [NebAny], NebBool), std_is_int) STD["int?"] = [is_int] is_float = FuncImpl(NebFunction("string?", [NebAny], NebBool), std_is_float) STD["float?"] = [is_float] is_number = FuncImpl(NebFunction("string?", [NebAny], NebBool), std_is_number) STD["number?"] = [is_number] is_bool = FuncImpl(NebFunction("string?", [NebAny], NebBool), std_is_bool) STD["bool?"] = [is_bool] build_std()