from .. import TypeEnum, Environment, Arg, Builtin, evaluate, InterpretPanic, NebType, TypeWrap, MultiFunction from ..structs import * TYPES = Environment() def interpretIsBool(symbol, args, env, ns): return Bool(isinstance(args[0], Bool)) isbool_func = Builtin("bool?", interpretIsBool, [Arg("arg", TypeEnum.ANY)], return_type=Type(":bool")) isbool_multi = MultiFunction("bool?") isbool_multi.register(isbool_func) TYPES.register("bool?", isbool_multi) def interpretIsFloat(symbol, args, env, ns): return Bool(isinstance(args[0], Float)) isfloat_func = Builtin("float?", interpretIsFloat, [Arg("arg", TypeEnum.ANY)], return_type=Type(":bool")) isfloat_multi = MultiFunction("float?") isfloat_multi.register(isfloat_func) TYPES.register("float?", isfloat_multi) def interpretIsNumber(symbol, args, env, ns): ret = isinstance(args[0], Int) or isinstance(args[0], Float) return Bool(ret) isnumber_func = Builtin("number?", interpretIsNumber, [Arg("arg", TypeEnum.ANY)], return_type=Type(":bool")) isnumber_multi = MultiFunction("number?") isnumber_multi.register(isnumber_func) TYPES.register("number?", isnumber_multi) def interpretIsInt(symbol, args, env, ns): return Bool(isinstance(args[0], Int)) isint_func = Builtin("int?", interpretIsInt, [Arg("arg", TypeEnum.ANY)], return_type=Type(":bool")) isint_multi = MultiFunction("int?") isint_multi.register(isint_func) TYPES.register("int?", isint_multi) def interpretIsList(symbol, args, env, ns): # if it's not a list, we're done if not (isinstance(args[0], List) or isinstance(args[0], Expr)): return Bool(False) # if the symbol isn't a type, we're done elif not isinstance(symbol, Type): return Bool(True) inner = symbol.inner if inner is None or inner.name == ":any": return Bool(True) inner_type = env.get(f"{inner.name}") for arg in args[0].args: valid = inner_type.validate_type(arg, env, ns) if valid.value is False: return Bool(False) return Bool(True) islist_func = Builtin("list?", interpretIsList, [Arg("arg", TypeEnum.ANY)], return_type=Type(":bool")) islist_multi = MultiFunction("list?") islist_multi.register(islist_func) TYPES.register("list?", islist_multi) def interpretIsNonEmptyList(symbol, args, env, ns): # if it's not a list, we're done if not (isinstance(args[0], List) or isinstance(args[0], Expr)): return Bool(False) # if it's empty, we're done elif len(args[0].args) == 0: return Bool(False) # if the symbol isn't a type, we're done elif not isinstance(symbol, Type): return Bool(True) inner = symbol.inner if inner is None or inner.name == ":any": return Bool(True) inner_type = env.get(f"{inner.name}") for arg in args[0].args: valid = inner_type.validate_type(arg, env, ns) if valid.value is False: return Bool(False) return Bool(True) def interpretIsString(symbol, args, env, ns): return Bool(isinstance(args[0], String)) isstring_func = Builtin("string?", interpretIsString, [Arg("arg", TypeEnum.ANY)], return_type=Type(":bool")) isstring_multi = MultiFunction("string?") isstring_multi.register(isstring_func) TYPES.register("string?", isstring_multi) def interpretStringToInt(symbol, args, env, ns): try: val = int(args[0].value) return Int(val) except: raise InterpretPanic(symbol, "can't convert to an :int", args[0]) stringtoint_func = Builtin("string->int", interpretStringToInt, [Arg("arg", TypeEnum.STRING)], return_type=Type(":int")) stringtoint_multi = MultiFunction("string->int") stringtoint_multi.register(stringtoint_func) TYPES.register("string->int", stringtoint_multi) def interpretStringToFloat(symbol, args, env, ns): try: val = float(args[0].value) return Float(val) except: raise InterpretPanic(symbol, "can't convert to a :float", args[0]) stringtofloat_func = Builtin("string->float", interpretStringToFloat, [Arg("arg", TypeEnum.STRING)], return_type=Type(":float")) stringtofloat_multi = MultiFunction("string->float") stringtofloat_multi.register(stringtofloat_func) TYPES.register("string->float", stringtofloat_multi) def interpretToString(symbol, args, env, ns): item = args[0] if isinstance(item, String): return item elif isinstance(item, Literal): return String(str(item)) else: return String(f"{item}") tostring_func = Builtin("->string", interpretToString, [Arg("arg", TypeEnum.ANY)], return_type=Type(":string")) tostring_multi = MultiFunction("->string") tostring_multi.register(tostring_func) TYPES.register("->string", tostring_multi) def interpretTypeOf(symbol, args, env, ns): return Type(f"{args[0].type_}") typeof_func = Builtin("typeof", interpretTypeOf, [Arg("candidate", TypeEnum.ANY)]) typeof_multi = MultiFunction("typeof") typeof_multi.register(typeof_func) TYPES.register("typeof", typeof_multi) def interpretIsAny(symbol, args, env, ns): return Bool(True) isany_func = Builtin("any?", interpretIsAny, [Arg("arg", TypeEnum.ANY)], return_type=Type(":bool")) isany_multi = MultiFunction("any?") isany_multi.register(isany_func) TYPES.register("any?", isany_multi) def interpretIsLiteral(symbol, args, env, ns): return Bool(isinstance(args[0], Literal)) isliteral_func = Builtin("literal?", interpretIsLiteral, [Arg("arg", TypeEnum.ANY)], return_type=Type(":bool")) isliteral_multi = MultiFunction("literal?") isliteral_multi.register(isliteral_func) TYPES.register("literal?", isliteral_multi) def interpretIsHandle(symbol, args, env, ns): return Bool(isinstance(args[0], Handle)) ishandle_func = Builtin("handle?", interpretIsHandle, [Arg("arg", TypeEnum.ANY)], return_type=Type(":bool")) ishandle_multi = MultiFunction("handle?") ishandle_multi.register(ishandle_func) TYPES.register("handle?", ishandle_multi) def interpretIsType(symbol, args, env, ns): return Bool(isinstance(args[0], TypeWrap)) istype_func = Builtin("type?", interpretIsType, [Arg("arg", TypeEnum.ANY)], return_type=Type(":bool")) istype_multi = MultiFunction("type?") istype_multi.register(istype_func) TYPES.register("type?", istype_multi) def interpretIsNil(symbol, args, env, ns): return Bool(isinstance(args[0], List) and len(args[0].args) == 0) isnil_func = Builtin("nil?", interpretIsNil, [Arg("arg", TypeEnum.ANY)], return_type=Type(":bool")) isnil_multi = MultiFunction("nil?") isnil_multi.register(isnil_func) TYPES.register("nil?", isnil_multi) # add types to env any_type = NebType(":any", None, interpretIsAny) literal_type = NebType(":literal", any_type, interpretIsLiteral) string_type = NebType(":string", literal_type, interpretIsString) #list_type = NebType(":list", any_type, interpretIsList) bracket_type = NebType(":[]", any_type, interpretIsList) nil_type = NebType(":nil", bracket_type, interpretIsNil) brace_type = NebType(":{}", any_type, interpretIsNonEmptyList) bool_type = NebType(":bool", literal_type, interpretIsBool) number_type = NebType(":number", literal_type, interpretIsNumber) int_type = NebType(":int", number_type, interpretIsInt) float_type = NebType(":float", number_type, interpretIsFloat) handle_type = NebType(":handle", any_type, interpretIsHandle) type_type = NebType(":type", any_type, interpretIsType) TYPES.register(":any", any_type) TYPES.register(":literal", literal_type) TYPES.register(":string", string_type) #TYPES.register(":list", list_type) TYPES.register(":[]", bracket_type) TYPES.register(":nil", nil_type) TYPES.register(":{}", brace_type) TYPES.register(":bool", bool_type) TYPES.register(":number", number_type) TYPES.register(":int", int_type) TYPES.register(":float", float_type) TYPES.register(":handle", handle_type) TYPES.register(":type", type_type)