#pragma once #include #include #include #include #include #include "utils.hpp" #include "types.hpp" namespace nodes { using namespace std; struct NodeInfo { optional type = std::nullopt; optional mode = std::nullopt; }; struct Expr; using ExprPtr = shared_ptr; using ExprPtrV = std::vector; struct Arg : public NodeInfo { Arg(string name) : name(std::move(name)) {} string name; }; struct Const : public NodeInfo { Const(int value) : value(value) {} int value; }; struct Var : public NodeInfo { Var(string name) : name(std::move(name)) {} string name; }; struct Let : public NodeInfo { Let(Arg name, ExprPtr body, ExprPtr where) : name(std::move(name)), body(body), where(where) {} Arg name; ExprPtr body; ExprPtr where; }; struct Lambda : public NodeInfo { Lambda(vector args, ExprPtr expr) : args(std::move(args)), expr(expr) {} vector args; ExprPtr expr; }; struct Call : public NodeInfo { Call(ExprPtr func, vector args) : func(func), args(std::move(args)) {} ExprPtr func; vector args; }; struct Condition : public NodeInfo { Condition(ExprPtr condition, ExprPtr then_case, ExprPtr else_case) : condition(condition), then_case(then_case), else_case(else_case) {} ExprPtr condition; ExprPtr then_case; ExprPtr else_case; }; // struct FunctionDecl { // string name; // vector args; // ExprPtr expr; // }; struct Expr { variant value; }; template ExprPtr make_expr(Args &&...args) { return std::make_shared(T(std::forward(args)...)); } template inline T with_type(T node, types::Type type) { node.type = std::move(type); return node; } template inline T with_mode(T node, types::Mode mode) { node.mode = std::move(mode); return node; } template inline T with_unique(T node) { return with_mode(node, types::Mode(types::Mode::Uniq::UNIQUE)); } inline ExprPtr make_var(std::string name, types::Mode mode = types::Mode()) { return make_expr(with_mode(Var(std::move(name)), mode)); } inline ExprPtr lambda1(string var, ExprPtr expr) { return make_expr(vector{Arg(var)}, std::move(expr)); } inline ExprPtr lambda1(Arg var, ExprPtr expr) { return make_expr(vector{var}, std::move(expr)); } inline ExprPtr operator_call(string name, ExprPtr left, ExprPtr right, types::Mode mode = types::Mode()) { return make_expr(make_var(name, mode), ExprPtrV{left, right}); } // TODO: all constructors } // namespace nodes