diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/hir/expr.cpp | 5 | ||||
-rw-r--r-- | src/hir/expr.hpp | 3 | ||||
-rw-r--r-- | src/hir/expr_ptr.hpp | 5 | ||||
-rw-r--r-- | src/hir/from_ast.cpp | 3 | ||||
-rw-r--r-- | src/hir/type.hpp | 1 | ||||
-rw-r--r-- | src/hir_conv/constant_evaluation.cpp | 176 | ||||
-rw-r--r-- | src/include/tagged_union.hpp | 2 |
7 files changed, 171 insertions, 24 deletions
diff --git a/src/hir/expr.cpp b/src/hir/expr.cpp index bb3bf0eb..59651c57 100644 --- a/src/hir/expr.cpp +++ b/src/hir/expr.cpp @@ -5,6 +5,11 @@ ::HIR::ExprNode::~ExprNode() { } +const Span& ::HIR::ExprNode::span() const +{ + static Span rv = Span(); + return rv; +} #define DEF_VISIT(nt, n, code) void ::HIR::nt::visit(ExprVisitor& nv) { nv.visit(*this); } void ::HIR::ExprVisitorDef::visit(::HIR::nt& n) { code } diff --git a/src/hir/expr.hpp b/src/hir/expr.hpp index 6a40d669..1f13bea7 100644 --- a/src/hir/expr.hpp +++ b/src/hir/expr.hpp @@ -5,6 +5,7 @@ #include <memory> #include <hir/pattern.hpp> #include <hir/type.hpp> +#include <span.hpp> namespace HIR { @@ -14,6 +15,8 @@ class ExprNode { public: //::HIR::TypeRef m_res_type; + + const Span& span() const; virtual void visit(ExprVisitor& v) = 0; virtual ~ExprNode(); diff --git a/src/hir/expr_ptr.hpp b/src/hir/expr_ptr.hpp index 59663310..0dcc300a 100644 --- a/src/hir/expr_ptr.hpp +++ b/src/hir/expr_ptr.hpp @@ -21,7 +21,10 @@ public: } ~ExprPtr(); - ::HIR::ExprNode& operator*() { return *node; } + ::HIR::ExprNode& operator*() { return *node; } + const ::HIR::ExprNode& operator*() const { return *node; } + ::HIR::ExprNode* operator->() { return node; } + const ::HIR::ExprNode* operator->() const { return node; } }; } // namespace HIR diff --git a/src/hir/from_ast.cpp b/src/hir/from_ast.cpp index 41ee37fd..011fb6c4 100644 --- a/src/hir/from_ast.cpp +++ b/src/hir/from_ast.cpp @@ -466,7 +466,8 @@ if( e.size ) { return ::HIR::TypeRef( ::HIR::TypeRef::Data::make_Array({ box$( LowerHIR_Type(*e.inner) ), - LowerHIR_Expr( e.size ) + LowerHIR_Expr( e.size ), + ~0u }) ); } else { diff --git a/src/hir/type.hpp b/src/hir/type.hpp index ca79a0c1..4b3692c0 100644 --- a/src/hir/type.hpp +++ b/src/hir/type.hpp @@ -74,6 +74,7 @@ struct TypeRef (Array, struct { ::std::unique_ptr<TypeRef> inner; ::HIR::ExprPtr size; + size_t size_val; }), (Slice, struct { ::std::unique_ptr<TypeRef> inner; diff --git a/src/hir_conv/constant_evaluation.cpp b/src/hir_conv/constant_evaluation.cpp index 7738861d..2544f85c 100644 --- a/src/hir_conv/constant_evaluation.cpp +++ b/src/hir_conv/constant_evaluation.cpp @@ -8,28 +8,49 @@ namespace { - ::HIR::Literal evaluate_constant(const ::HIR::Crate& crate, ::HIR::ExprNode& expr) + ::HIR::Function& get_function(const Span& sp, const ::HIR::Crate& crate, const ::HIR::Path& path) + { + TU_MATCH(::HIR::Path::Data, (path.m_data), (e), + (Generic, + TODO(sp, "get_function(path = " << path << ")"); + ), + (UfcsInherent, + // Easy (ish) + TODO(sp, "get_function(path = " << path << ")"); + ), + (UfcsKnown, + TODO(sp, "get_function(path = " << path << ")"); + ), + (UfcsUnknown, + // TODO - Since this isn't known, can it be searched properly? + TODO(sp, "get_function(path = " << path << ")"); + ) + ) + throw ""; + } + + ::HIR::Literal evaluate_constant(const ::HIR::Crate& crate, const ::HIR::ExprNode& expr) { struct Visitor: public ::HIR::ExprVisitor { - const ::HIR::Crate& crate; + const ::HIR::Crate& m_crate; ::HIR::Literal m_rv; Visitor(const ::HIR::Crate& crate): - crate(crate) + m_crate(crate) {} void badnode(const ::HIR::ExprNode& node) const { - ERROR(Span(), E0000, "Node not allowed in constant expression"); + ERROR(node.span(), E0000, "Node not allowed in constant expression"); } void visit(::HIR::ExprNode_Block& node) override { - TODO(Span(), "ExprNode_Block"); + TODO(node.span(), "ExprNode_Block"); } void visit(::HIR::ExprNode_Return& node) override { - TODO(Span(), "ExprNode_Return"); + TODO(node.span(), "ExprNode_Return"); } void visit(::HIR::ExprNode_Let& node) override { badnode(node); @@ -51,13 +72,107 @@ namespace { badnode(node); } void visit(::HIR::ExprNode_BinOp& node) override { - TODO(Span(), "ExprNode_BinOp"); + node.m_left->visit(*this); + auto left = mv$(m_rv); + node.m_right->visit(*this); + auto right = mv$(m_rv); + + if( left.tag() != right.tag() ) { + ERROR(node.span(), E0000, "ExprNode_BinOp - Sides mismatched"); + } + + switch(node.m_op) + { + case ::HIR::ExprNode_BinOp::Op::CmpEqu: + case ::HIR::ExprNode_BinOp::Op::CmpNEqu: + case ::HIR::ExprNode_BinOp::Op::CmpLt: + case ::HIR::ExprNode_BinOp::Op::CmpLtE: + case ::HIR::ExprNode_BinOp::Op::CmpGt: + case ::HIR::ExprNode_BinOp::Op::CmpGtE: + ERROR(node.span(), E0000, "ExprNode_BinOp - Comparisons"); + break; + case ::HIR::ExprNode_BinOp::Op::BoolAnd: + case ::HIR::ExprNode_BinOp::Op::BoolOr: + ERROR(node.span(), E0000, "ExprNode_BinOp - Logicals"); + break; + + case ::HIR::ExprNode_BinOp::Op::Add: + TU_MATCH_DEF(::HIR::Literal, (left, right), (le, re), + ( throw ""; ), + (Integer, m_rv = ::HIR::Literal(le + re); ), + (Float, m_rv = ::HIR::Literal(le + re); ) + ) + break; + case ::HIR::ExprNode_BinOp::Op::Sub: + TU_MATCH_DEF(::HIR::Literal, (left, right), (le, re), + ( throw ""; ), + (Integer, m_rv = ::HIR::Literal(le - re); ), + (Float, m_rv = ::HIR::Literal(le - re); ) + ) + break; + case ::HIR::ExprNode_BinOp::Op::Mul: + TU_MATCH_DEF(::HIR::Literal, (left, right), (le, re), + ( throw ""; ), + (Integer, m_rv = ::HIR::Literal(le * re); ), + (Float, m_rv = ::HIR::Literal(le * re); ) + ) + break; + case ::HIR::ExprNode_BinOp::Op::Div: + TU_MATCH_DEF(::HIR::Literal, (left, right), (le, re), + ( throw ""; ), + (Integer, m_rv = ::HIR::Literal(le / re); ), + (Float, m_rv = ::HIR::Literal(le / re); ) + ) + break; + case ::HIR::ExprNode_BinOp::Op::Mod: + TU_MATCH_DEF(::HIR::Literal, (left, right), (le, re), + ( throw ""; ), + (Integer, m_rv = ::HIR::Literal(le % re); ), + (Float, ERROR(node.span(), E0000, "modulo operator on float in constant"); ) + ) + break; + case ::HIR::ExprNode_BinOp::Op::And: + TU_MATCH_DEF(::HIR::Literal, (left, right), (le, re), + ( throw ""; ), + (Integer, m_rv = ::HIR::Literal(le % re); ), + (Float, ERROR(node.span(), E0000, "bitwise and operator on float in constant"); ) + ) + break; + case ::HIR::ExprNode_BinOp::Op::Or: + TU_MATCH_DEF(::HIR::Literal, (left, right), (le, re), + ( throw ""; ), + (Integer, m_rv = ::HIR::Literal(le | re); ), + (Float, ERROR(node.span(), E0000, "bitwise or operator on float in constant"); ) + ) + break; + case ::HIR::ExprNode_BinOp::Op::Xor: + TU_MATCH_DEF(::HIR::Literal, (left, right), (le, re), + ( throw ""; ), + (Integer, m_rv = ::HIR::Literal(le ^ re); ), + (Float, ERROR(node.span(), E0000, "bitwise xor operator on float in constant"); ) + ) + break; + case ::HIR::ExprNode_BinOp::Op::Shr: + TU_MATCH_DEF(::HIR::Literal, (left, right), (le, re), + ( throw ""; ), + (Integer, m_rv = ::HIR::Literal(le >> re); ), + (Float, ERROR(node.span(), E0000, "bitwise shift right operator on float in constant"); ) + ) + break; + case ::HIR::ExprNode_BinOp::Op::Shl: + TU_MATCH_DEF(::HIR::Literal, (left, right), (le, re), + ( throw ""; ), + (Integer, m_rv = ::HIR::Literal(le << re); ), + (Float, ERROR(node.span(), E0000, "bitwise shift left operator on float in constant"); ) + ) + break; + } } void visit(::HIR::ExprNode_UniOp& node) override { - TODO(Span(), "ExprNode_UniOp"); + TODO(node.span(), "ExprNode_UniOp"); } void visit(::HIR::ExprNode_Cast& node) override { - TODO(Span(), "ExprNode_Cast"); + TODO(node.span(), "ExprNode_Cast"); } void visit(::HIR::ExprNode_Index& node) override { badnode(node); @@ -67,7 +182,17 @@ namespace { } void visit(::HIR::ExprNode_CallPath& node) override { - TODO(Span(), "exec const fn"); + ::std::vector<HIR::Literal> arg_vals; + for(const auto& arg : node.m_args) { + arg->visit(*this); + arg_vals.push_back( mv$(m_rv) ); + } + + auto& fcn = get_function(node.span(), m_crate, node.m_path); + if( ! fcn.m_const ) { + ERROR(node.span(), E0000, "Calling non-const function in const context"); + } + TODO(node.span(), "exec const fn - " << node.m_path); } void visit(::HIR::ExprNode_CallValue& node) override { badnode(node); @@ -95,29 +220,29 @@ namespace { m_rv = ::HIR::Literal(e); ), (ByteString, - TODO(Span(), "Byte literal in constant"); + TODO(node.span(), "Byte literal in constant"); //m_rv = ::HIR::Literal::make_String(e); ) ) } void visit(::HIR::ExprNode_PathValue& node) override { - TODO(Span(), "ExprNode_PathValue"); + TODO(node.span(), "ExprNode_PathValue"); } void visit(::HIR::ExprNode_Variable& node) override { - TODO(Span(), "ExprNode_Variable"); + TODO(node.span(), "ExprNode_Variable"); } void visit(::HIR::ExprNode_StructLiteral& node) override { - TODO(Span(), "ExprNode_StructLiteral"); + TODO(node.span(), "ExprNode_StructLiteral"); } void visit(::HIR::ExprNode_Tuple& node) override { - TODO(Span(), "ExprNode_Tuple"); + TODO(node.span(), "ExprNode_Tuple"); } void visit(::HIR::ExprNode_ArrayList& node) override { - TODO(Span(), "ExprNode_ArrayList"); + TODO(node.span(), "ExprNode_ArrayList"); } void visit(::HIR::ExprNode_ArraySized& node) override { - TODO(Span(), "ExprNode_ArraySized"); + TODO(node.span(), "ExprNode_ArraySized"); } void visit(::HIR::ExprNode_Closure& node) override { @@ -126,7 +251,7 @@ namespace { }; Visitor v { crate }; - expr.visit(v); + const_cast<::HIR::ExprNode&>(expr).visit(v); if( v.m_rv.is_Invalid() ) { BUG(Span(), "Expression did not yeild a literal"); @@ -150,13 +275,21 @@ namespace { TU_IFLET(::HIR::TypeRef::Data, ty.m_data, Array, e, ::HIR::Visitor::visit_type(*e.inner); assert(&*e.size != nullptr); - auto size = evaluate_constant(m_crate, *e.size); - TODO(Span(), "visit_type - Set array size to " << size << ", ty = " << ty); + auto val = evaluate_constant(m_crate, *e.size); + if( !val.is_Integer() ) + ERROR(e.size->span(), E0000, "Array size isn't an integer"); + e.size_val = val.as_Integer(); + DEBUG("Array " << ty << " - size = " << e.size_val); ) else { ::HIR::Visitor::visit_type(ty); } } + void visit_constant(::HIR::Constant& item) override + { + item.m_value_res = evaluate_constant(m_crate, *item.m_value); + DEBUG("constant = " << item.m_value_res); + } void visit_expr(::HIR::ExprPtr& expr) override { struct Visitor: @@ -171,8 +304,9 @@ namespace { void visit(::HIR::ExprNode_ArraySized& node) override { auto val = evaluate_constant(m_crate, *node.m_size); if( !val.is_Integer() ) - ERROR(Span(), E0000, "Array size isn't an integer"); + ERROR(node.span(), E0000, "Array size isn't an integer"); node.m_size_val = val.as_Integer(); + DEBUG("Array literal [?; " << node.m_size_val << "]"); } }; diff --git a/src/include/tagged_union.hpp b/src/include/tagged_union.hpp index dd9ce056..213ebceb 100644 --- a/src/include/tagged_union.hpp +++ b/src/include/tagged_union.hpp @@ -109,7 +109,7 @@ */} #define TU_MATCH_BIND1(TAG, VAR, NAME) /*MATCH_BIND*/ auto& NAME = (VAR).as_##TAG(); (void)&NAME; #define TU_MATCH_BIND2_(TAG, v1,v2, n1,n2) TU_MATCH_BIND1(TAG, v1, n1) TU_MATCH_BIND1(TAG, v2, n2) -#define TU_MATCH_BIND2(...) TU_MATCH_BIND2_(__VA_ARGS__) +#define TU_MATCH_BIND2(...) TU_MATCH_BIND2_(__VA_ARGS__) // << Exists to cause expansion of the vars #define TU_MATCH_ARM(CLASS, VAR, NAME, TAG, ...) case CLASS::TAG_##TAG: {/* */ TU_GM(TU_MATCH_BIND, TU_EXP VAR)(TAG, TU_EXP VAR , TU_EXP NAME)/* */ __VA_ARGS__/* |