#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace Fig::Builtins { const TypeInfo &getErrorInterfaceTypeInfo() { static const TypeInfo ErrorInterfaceTypeInfo(U"Error", true); return ErrorInterfaceTypeInfo; } const TypeInfo &getTypeErrorStructTypeInfo() { static const TypeInfo TypeErrorStructTypeInfo(U"TypeError", true); return TypeErrorStructTypeInfo; } const TypeInfo &getOperationInterfaceTypeInfo() { static const TypeInfo OperationInterfaceTypeInfo(U"Operation", true); return OperationInterfaceTypeInfo; } const std::unordered_map &getBuiltinValues() { static const std::unordered_map builtinValues = { {U"null", Object::getNullInstance()}, {U"true", Object::getTrueInstance()}, {U"false", Object::getFalseInstance()}, {U"Error", std::make_shared(InterfaceType(getErrorInterfaceTypeInfo(), {Ast::InterfaceMethod(U"toString", Ast::FunctionParameters({}, {}), std::make_shared(U"String"), nullptr), Ast::InterfaceMethod(U"getErrorClass", Ast::FunctionParameters({}, {}), std::make_shared(U"String"), nullptr), Ast::InterfaceMethod(U"getErrorMessage", Ast::FunctionParameters({}, {}), std::make_shared(U"String"), nullptr)}))}, {U"TypeError", std::make_shared(StructType( getTypeErrorStructTypeInfo(), std::make_shared(U""), {Field(AccessModifier::Public, U"msg", ValueType::String, nullptr)} ))}, {U"Operation", std::make_shared(InterfaceType(getOperationInterfaceTypeInfo(), {}))}, {U"Any", std::make_shared(StructType(ValueType::Any, nullptr, {}, true))}, {U"Int", std::make_shared(StructType(ValueType::Int, nullptr, {}, true))}, {U"Null", std::make_shared(StructType(ValueType::Null, nullptr, {}, true))}, {U"String", std::make_shared(StructType(ValueType::String, nullptr, {}, true))}, {U"Bool", std::make_shared(StructType(ValueType::Bool, nullptr, {}, true))}, {U"Double", std::make_shared(StructType(ValueType::Double, nullptr, {}, true))}, {U"Function", std::make_shared(StructType(ValueType::Function, nullptr, {}, true))}, {U"List", std::make_shared(StructType(ValueType::List, nullptr, {}, true))}, {U"Map", std::make_shared(StructType(ValueType::Map, nullptr, {}, true))}, // Type `StructType` `StructInstance` `Module` `InterfaceType` // Not allowed to call constructor! {U"type", std::make_shared(Function( U"type", [](const std::vector &_args) -> ObjectPtr { const ObjectPtr &arg = _args[0]; return std::make_shared(prettyType(arg)); }, 1 ))}, }; return builtinValues; } const std::unordered_map &getBuiltinFunctionArgCounts() { static const std::unordered_map builtinFunctionArgCounts = { {U"__fstdout_print", -1}, // variadic {U"__fstdout_println", -1}, // variadic {U"__fstdin_read", 0}, {U"__fstdin_readln", 0}, {U"__fvalue_type", 1}, {U"__fvalue_int_parse", 1}, {U"__fvalue_int_from", 1}, {U"__fvalue_double_parse", 1}, {U"__fvalue_double_from", 1}, {U"__fvalue_string_from", 1}, {U"__ftime_now_ns", 0}, /* math start */ {U"__fmath_acos", 1}, {U"__fmath_acosh", 1}, {U"__fmath_asin", 1}, {U"__fmath_asinh", 1}, {U"__fmath_atan", 1}, {U"__fmath_atan2", 2}, {U"__fmath_atanh", 1}, {U"__fmath_ceil", 1}, {U"__fmath_cos", 1}, {U"__fmath_cosh", 1}, {U"__fmath_exp", 1}, {U"__fmath_expm1", 1}, {U"__fmath_fabs", 1}, {U"__fmath_floor", 1}, {U"__fmath_fmod", 2}, {U"__fmath_frexp", 1}, {U"__fmath_gcd", 2}, {U"__fmath_hypot", 2}, {U"__fmath_isequal", 2}, {U"__fmath_log", 1}, {U"__fmath_log10", 1}, {U"__fmath_log1p", 1}, {U"__fmath_log2", 1}, {U"__fmath_sin", 1}, {U"__fmath_sinh", 1}, {U"__fmath_sqrt", 1}, {U"__fmath_tan", 1}, {U"__fmath_tanh", 1}, {U"__fmath_trunc", 1}, }; return builtinFunctionArgCounts; } const std::unordered_map &getBuiltinFunctions() { static const std::unordered_map builtinFunctions{ {U"__fstdout_print", [](const std::vector &args) -> ObjectPtr { for (auto arg : args) { std::print("{}", arg->toStringIO().toBasicString()); } return std::make_shared(ValueType::IntClass(args.size())); }}, {U"__fstdout_println", [](const std::vector &args) -> ObjectPtr { for (auto arg : args) { std::print("{}", arg->toStringIO().toBasicString()); } std::print("\n"); return std::make_shared(ValueType::IntClass(args.size())); }}, {U"__fstdin_read", [](const std::vector &args) -> ObjectPtr { std::string input; std::cin >> input; return std::make_shared(String(input)); }}, {U"__fstdin_readln", [](const std::vector &args) -> ObjectPtr { std::string line; std::getline(std::cin, line); return std::make_shared(String(line)); }}, {U"__fvalue_type", [](const std::vector &args) -> ObjectPtr { return std::make_shared(args[0]->getTypeInfo().toString()); }}, {U"__fvalue_int_parse", [](const std::vector &args) -> ObjectPtr { String str = args[0]->as(); try { ValueType::IntClass val = std::stoi(str.toBasicString()); return std::make_shared(val); } catch (...) { throw RuntimeError(String(std::format("Invalid int string for parsing", str.toBasicString()))); } }}, {U"__fvalue_int_from", [](const std::vector &args) -> ObjectPtr { ObjectPtr val = args[0]; if (val->is()) { return std::make_shared( static_cast(val->as())); } else if (val->is()) { return std::make_shared( static_cast(val->as() ? 1 : 0)); } else { throw RuntimeError(String(std::format("Type '{}' cannot be converted to int", val->getTypeInfo().toString().toBasicString()))); } }}, {U"__fvalue_double_parse", [](const std::vector &args) -> ObjectPtr { String str = args[0]->as(); try { ValueType::DoubleClass val = std::stod(str.toBasicString()); return std::make_shared(ValueType::DoubleClass(val)); } catch (...) { throw RuntimeError(String(std::format("Invalid double string for parsing", str.toBasicString()))); } }}, {U"__fvalue_double_from", [](const std::vector &args) -> ObjectPtr { ObjectPtr val = args[0]; if (val->is()) { return std::make_shared( static_cast(val->as())); } else if (val->is()) { return std::make_shared( ValueType::DoubleClass(val->as() ? 1.0 : 0.0)); } else { throw RuntimeError(String(std::format("Type '{}' cannot be converted to double", val->getTypeInfo().toString().toBasicString()))); } }}, {U"__fvalue_string_from", [](const std::vector &args) -> ObjectPtr { ObjectPtr val = args[0]; return std::make_shared(val->toStringIO()); }}, {U"__ftime_now_ns", [](const std::vector &args) -> ObjectPtr { // returns nanoseconds using namespace Fig::Time; auto now = Clock::now(); return std::make_shared(static_cast( std::chrono::duration_cast(now - start_time).count())); }}, /* math start */ {U"__fmath_acos", [](const std::vector &args) -> ObjectPtr { ObjectPtr val = args[0]; ValueType::DoubleClass d = val->getNumericValue(); return std::make_shared(acos(d)); }}, {U"__fmath_acosh", [](const std::vector &args) -> ObjectPtr { ObjectPtr val = args[0]; ValueType::DoubleClass d = val->getNumericValue(); return std::make_shared(acosh(d)); }}, {U"__fmath_asin", [](const std::vector &args) -> ObjectPtr { ObjectPtr val = args[0]; ValueType::DoubleClass d = val->getNumericValue(); return std::make_shared(asin(d)); }}, {U"__fmath_asinh", [](const std::vector &args) -> ObjectPtr { ObjectPtr val = args[0]; ValueType::DoubleClass d = val->getNumericValue(); return std::make_shared(asinh(d)); }}, {U"__fmath_atan", [](const std::vector &args) -> ObjectPtr { ObjectPtr val = args[0]; ValueType::DoubleClass d = val->getNumericValue(); return std::make_shared(atan(d)); }}, {U"__fmath_atan2", [](const std::vector &args) -> ObjectPtr { ValueType::DoubleClass y = args[0]->getNumericValue(); ValueType::DoubleClass x = args[1]->getNumericValue(); return std::make_shared(atan2(y, x)); }}, {U"__fmath_atanh", [](const std::vector &args) -> ObjectPtr { ObjectPtr val = args[0]; ValueType::DoubleClass d = val->getNumericValue(); return std::make_shared(atanh(d)); }}, {U"__fmath_ceil", [](const std::vector &args) -> ObjectPtr { ObjectPtr val = args[0]; ValueType::DoubleClass d = val->getNumericValue(); return std::make_shared(ceil(d)); }}, {U"__fmath_cos", [](const std::vector &args) -> ObjectPtr { ObjectPtr val = args[0]; ValueType::DoubleClass d = val->getNumericValue(); return std::make_shared(cos(d)); }}, {U"__fmath_cosh", [](const std::vector &args) -> ObjectPtr { ObjectPtr val = args[0]; ValueType::DoubleClass d = val->getNumericValue(); return std::make_shared(cosh(d)); }}, {U"__fmath_exp", [](const std::vector &args) -> ObjectPtr { ObjectPtr val = args[0]; ValueType::DoubleClass d = val->getNumericValue(); return std::make_shared(exp(d)); }}, {U"__fmath_expm1", [](const std::vector &args) -> ObjectPtr { ObjectPtr val = args[0]; ValueType::DoubleClass d = val->getNumericValue(); return std::make_shared(expm1(d)); }}, {U"__fmath_fabs", [](const std::vector &args) -> ObjectPtr { ObjectPtr val = args[0]; ValueType::DoubleClass d = val->getNumericValue(); return std::make_shared(fabs(d)); }}, {U"__fmath_floor", [](const std::vector &args) -> ObjectPtr { ObjectPtr val = args[0]; ValueType::DoubleClass d = val->getNumericValue(); return std::make_shared(floor(d)); }}, {U"__fmath_fmod", [](const std::vector &args) -> ObjectPtr { ValueType::DoubleClass x = args[0]->getNumericValue(); ValueType::DoubleClass y = args[1]->getNumericValue(); return std::make_shared(fmod(x, y)); }}, {U"__fmath_frexp", [](const std::vector &args) -> ObjectPtr { ObjectPtr val = args[0]; ValueType::DoubleClass d = val->getNumericValue(); int e; return std::make_shared(List({std::make_shared(frexp(d, &e)), std::make_shared(static_cast(e))})); }}, {U"__fmath_gcd", [](const std::vector &args) -> ObjectPtr { ValueType::IntClass x = args[0]->as(); ValueType::IntClass y = args[1]->as(); return std::make_shared(std::gcd(x, y)); }}, {U"__fmath_hypot", [](const std::vector &args) -> ObjectPtr { ValueType::DoubleClass x = args[0]->getNumericValue(); ValueType::DoubleClass y = args[1]->getNumericValue(); return std::make_shared(hypot(x, y)); }}, {U"__fmath_isequal", [](const std::vector &args) -> ObjectPtr { ValueType::DoubleClass x = args[0]->getNumericValue(); ValueType::DoubleClass y = args[1]->getNumericValue(); static const double epsilon = 1e-9; return std::make_shared(fabs(x - y) < epsilon); }}, {U"__fmath_log", [](const std::vector &args) -> ObjectPtr { ObjectPtr val = args[0]; ValueType::DoubleClass d = val->getNumericValue(); return std::make_shared(log(d)); }}, {U"__fmath_log10", [](const std::vector &args) -> ObjectPtr { ObjectPtr val = args[0]; ValueType::DoubleClass d = val->getNumericValue(); return std::make_shared(log10(d)); }}, {U"__fmath_log1p", [](const std::vector &args) -> ObjectPtr { ObjectPtr val = args[0]; ValueType::DoubleClass d = val->getNumericValue(); return std::make_shared(log1p(d)); }}, {U"__fmath_log2", [](const std::vector &args) -> ObjectPtr { ObjectPtr val = args[0]; ValueType::DoubleClass d = val->getNumericValue(); return std::make_shared(log2(d)); }}, {U"__fmath_sin", [](const std::vector &args) -> ObjectPtr { ObjectPtr val = args[0]; ValueType::DoubleClass d = val->getNumericValue(); return std::make_shared(sin(d)); }}, {U"__fmath_sinh", [](const std::vector &args) -> ObjectPtr { ObjectPtr val = args[0]; ValueType::DoubleClass d = val->getNumericValue(); return std::make_shared(sinh(d)); }}, {U"__fmath_sqrt", [](const std::vector &args) -> ObjectPtr { ObjectPtr val = args[0]; ValueType::DoubleClass d = val->getNumericValue(); return std::make_shared(sqrt(d)); }}, {U"__fmath_tan", [](const std::vector &args) -> ObjectPtr { ObjectPtr val = args[0]; ValueType::DoubleClass d = val->getNumericValue(); return std::make_shared(tan(d)); }}, {U"__fmath_tanh", [](const std::vector &args) -> ObjectPtr { ObjectPtr val = args[0]; ValueType::DoubleClass d = val->getNumericValue(); return std::make_shared(tanh(d)); }}, {U"__fmath_trunc", [](const std::vector &args) -> ObjectPtr { ObjectPtr val = args[0]; ValueType::DoubleClass d = val->getNumericValue(); return std::make_shared(trunc(d)); }}, }; return builtinFunctions; } } // namespace Fig::Builtins