#include "fun.hpp" #define NUM_BINOP(OP)\ auto lhs = args[0]; \ auto rhs = args[1]; \ bool res = false; \ \ if (lhs->type() == TYPE_INT) \ { \ res = std::get(lhs->value()) OP std::get(rhs->value()); \ } \ \ if (lhs->type() == TYPE_FLOAT) \ { \ res = std::get(lhs->value()) OP std::get(rhs->value()); \ } \ \ return std::make_shared(TYPE_BOOL, res, loc) namespace fkstd { STDRET assert_eq(Loc loc, Module&, STDARGS args) { auto oracle = args[0]; auto expr = args[1]; if (!oracle->equals(*expr)) { std::stringstream ss; ss << "assertion failed: expected '" << oracle->string() << "', got '" << expr->string() << "'"; loc.error(LOG_ERROR, ss.str()); } return std::make_shared(TYPE_BOOL, true, loc); } STDRET println(Loc loc, Module&, STDARGS args) { std::string sep; for (auto arg: args) { std::cout << sep << arg->string(); sep = " "; } if (args.size() > 0) { loc = args.front()->loc(); } std::cout << std::endl; return std::make_shared(TYPE_INT, 0, loc); } STDRET add_int(Loc loc, Module&, STDARGS args) { int result = 0; for (auto arg: args) { result += std::get(arg->value()); } return std::make_shared(TYPE_INT, result, loc); } STDRET sub_int(Loc loc, Module&, STDARGS args) { if (args.empty()) { return std::make_shared(TYPE_INT, 0, loc); } if (args.size() == 1) { return std::make_shared(TYPE_INT, -std::get(args[0]->value()), loc); } int result = std::get(args[0]->value()); for (size_t i=1; i(args[i]->value()); } return std::make_shared(TYPE_INT, result, loc); } STDRET mul_int(Loc loc, Module&, STDARGS args) { int result = 1; for (auto arg: args) { result *= std::get(arg->value()); } return std::make_shared(TYPE_INT, result, loc); } STDRET div_int(Loc loc, Module&, STDARGS args) { if (args.empty()) { return std::make_shared(TYPE_INT, 1, loc); } if (args.size() == 1) { return std::make_shared(TYPE_INT, 1/std::get(args[0]->value()), loc); } int result = std::get(args[0]->value()); for (size_t i=1; i(args[i]->value()); } return std::make_shared(TYPE_INT, result, loc); } STDRET mod_int(Loc loc, Module&, STDARGS args) { if (args.empty()) { return std::make_shared(TYPE_INT, 1, loc); } int result = std::get(args[0]->value()); for (size_t i=1; i(args[i]->value()); } return std::make_shared(TYPE_INT, result, loc); } STDRET pow_int(Loc loc, Module&, STDARGS args) { if (args.empty()) { return std::make_shared(TYPE_INT, 1, loc); } int result = std::get(args[0]->value()); for (size_t i=1; i(args[i]->value())); } return std::make_shared(TYPE_INT, result, loc); } STDRET add_float(Loc loc, Module&, STDARGS args) { if (args.empty()) { return std::make_shared(TYPE_FLOAT, 0.0f, loc); } float result = std::get(args[0]->value()); for (size_t i=1; i(args[i]->value()); } return std::make_shared(TYPE_FLOAT, result, loc); } STDRET sub_float(Loc loc, Module&, STDARGS args) { if (args.empty()) { return std::make_shared(TYPE_FLOAT, 0.0f, loc); } float result = std::get(args[0]->value()); for (size_t i=1; i(args[i]->value()); } if (args.size() == 1) { return std::make_shared(TYPE_FLOAT, -result, loc); } return std::make_shared(TYPE_FLOAT, result, loc); } STDRET mul_float(Loc loc, Module&, STDARGS args) { if (args.empty()) { return std::make_shared(TYPE_FLOAT, 1.0f, loc); } float result = std::get(args[0]->value()); for (size_t i=1; i(args[i]->value()); } return std::make_shared(TYPE_FLOAT, result, loc); } STDRET div_float(Loc loc, Module&, STDARGS args) { if (args.empty()) { return std::make_shared(TYPE_FLOAT, 1.0f, loc); } float result = std::get(args[0]->value()); for (size_t i=1; i(args[i]->value()); } if (args.size() == 1) { return std::make_shared(TYPE_FLOAT, 1.0f/result, loc); } return std::make_shared(TYPE_FLOAT, result, loc); } STDRET mod_float(Loc loc, Module&, STDARGS args) { if (args.empty()) { return std::make_shared(TYPE_FLOAT, 1.0f, loc); } float result = std::get(args[0]->value()); for (size_t i=1; i(args[i]->value())); } return std::make_shared(TYPE_FLOAT, result, loc); } STDRET pow_float(Loc loc, Module&, STDARGS args) { if (args.empty()) { return std::make_shared(TYPE_FLOAT, 1.0f, loc); } float result = std::get(args[0]->value()); for (size_t i=1; i(args[i]->value())); } return std::make_shared(TYPE_FLOAT, result, loc); } STDRET lt(Loc loc, Module&, STDARGS args) { NUM_BINOP(<); } STDRET le(Loc loc, Module&, STDARGS args) { NUM_BINOP(<=); } STDRET gt(Loc loc, Module&, STDARGS args) { NUM_BINOP(>); } STDRET ge(Loc loc, Module&, STDARGS args) { NUM_BINOP(>=); } STDRET eq(Loc loc, Module&, STDARGS args) { NUM_BINOP(==); } STDRET ne(Loc loc, Module&, STDARGS args) { NUM_BINOP(!=); } STDRET bool_not(Loc loc, Module&, STDARGS args) { bool val = std::get(args[0]->value()); return std::make_shared(TYPE_BOOL, !val, loc); } STDRET array_ref(Loc, Module& mod, STDARGS args) { auto ref_val = args[0]->value(); size_t ref = std::get(ref_val); std::shared_ptr val = std::get>(mod.vm()->load_global(ref)); for (size_t i=1; i(args[i]->value()); auto ref_val = val->at(k)->value(); size_t ref = std::get(ref_val); auto arr = std::get>(mod.vm()->load_global(ref)); val = arr; } return val->at(std::get(args.back()->value())); } STDRET array_set(Loc, Module& mod, STDARGS args) { auto ref_val = args[0]->value(); size_t ref = std::get(ref_val); int index = std::get(args[1]->value()); std::shared_ptr val = std::get>(mod.vm()->load_global(ref)); val->set(index, args[2]); return args[2]; } STDRET string_cat(Loc loc, Module&, STDARGS args) { if (args.empty()) { return std::make_shared(TYPE_STRING, "", loc); } std::string value = std::get(args[0]->value()); for (size_t i=1; i(args[i]->value()); } return std::make_shared(TYPE_STRING, value, loc); } STDRET string_dup(Loc loc, Module&, STDARGS args) { std::string str = std::get(args[0]->value()); int n = std::get(args[1]->value()); std::string res; for (int i=0; i(TYPE_STRING, res, loc); } STDRET char_at(Loc loc, Module&, STDARGS args) { std::string str = std::get(args[0]->value()); int n = std::get(args[1]->value()); return std::make_shared(TYPE_STRING, std::string(1, str[n]), loc); } }