#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 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())); } }