summaryrefslogtreecommitdiff
path: root/src/hir_conv/constant_evaluation.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/hir_conv/constant_evaluation.cpp')
-rw-r--r--src/hir_conv/constant_evaluation.cpp184
1 files changed, 183 insertions, 1 deletions
diff --git a/src/hir_conv/constant_evaluation.cpp b/src/hir_conv/constant_evaluation.cpp
index 0c8fe8fd..7738861d 100644
--- a/src/hir_conv/constant_evaluation.cpp
+++ b/src/hir_conv/constant_evaluation.cpp
@@ -4,7 +4,189 @@
#include "main_bindings.hpp"
#include <hir/hir.hpp>
#include <hir/expr.hpp>
+#include <hir/visitor.hpp>
-void ConvertHIR_ConstantEvaluate(::HIR::Crate& hir_crate)
+
+namespace {
+ ::HIR::Literal evaluate_constant(const ::HIR::Crate& crate, ::HIR::ExprNode& expr)
+ {
+ struct Visitor:
+ public ::HIR::ExprVisitor
+ {
+ const ::HIR::Crate& crate;
+
+ ::HIR::Literal m_rv;
+
+ Visitor(const ::HIR::Crate& crate):
+ crate(crate)
+ {}
+
+ void badnode(const ::HIR::ExprNode& node) const {
+ ERROR(Span(), E0000, "Node not allowed in constant expression");
+ }
+
+ void visit(::HIR::ExprNode_Block& node) override {
+ TODO(Span(), "ExprNode_Block");
+ }
+ void visit(::HIR::ExprNode_Return& node) override {
+ TODO(Span(), "ExprNode_Return");
+ }
+ void visit(::HIR::ExprNode_Let& node) override {
+ badnode(node);
+ }
+ void visit(::HIR::ExprNode_Loop& node) override {
+ badnode(node);
+ }
+ void visit(::HIR::ExprNode_LoopControl& node) override {
+ badnode(node);
+ }
+ void visit(::HIR::ExprNode_Match& node) override {
+ badnode(node);
+ }
+ void visit(::HIR::ExprNode_If& node) override {
+ badnode(node);
+ }
+
+ void visit(::HIR::ExprNode_Assign& node) override {
+ badnode(node);
+ }
+ void visit(::HIR::ExprNode_BinOp& node) override {
+ TODO(Span(), "ExprNode_BinOp");
+ }
+ void visit(::HIR::ExprNode_UniOp& node) override {
+ TODO(Span(), "ExprNode_UniOp");
+ }
+ void visit(::HIR::ExprNode_Cast& node) override {
+ TODO(Span(), "ExprNode_Cast");
+ }
+ void visit(::HIR::ExprNode_Index& node) override {
+ badnode(node);
+ }
+ void visit(::HIR::ExprNode_Deref& node) override {
+ badnode(node);
+ }
+
+ void visit(::HIR::ExprNode_CallPath& node) override {
+ TODO(Span(), "exec const fn");
+ }
+ void visit(::HIR::ExprNode_CallValue& node) override {
+ badnode(node);
+ }
+ void visit(::HIR::ExprNode_CallMethod& node) override {
+ // TODO: const methods
+ badnode(node);
+ }
+ void visit(::HIR::ExprNode_Field& node) override {
+ badnode(node);
+ }
+
+ void visit(::HIR::ExprNode_Literal& node) override {
+ TU_MATCH(::HIR::ExprNode_Literal::Data, (node.m_data), (e),
+ (Integer,
+ m_rv = ::HIR::Literal(e.m_value);
+ ),
+ (Float,
+ m_rv = ::HIR::Literal(e.m_value);
+ ),
+ (Boolean,
+ m_rv = ::HIR::Literal(static_cast<uint64_t>(e));
+ ),
+ (String,
+ m_rv = ::HIR::Literal(e);
+ ),
+ (ByteString,
+ TODO(Span(), "Byte literal in constant");
+ //m_rv = ::HIR::Literal::make_String(e);
+ )
+ )
+ }
+ void visit(::HIR::ExprNode_PathValue& node) override {
+ TODO(Span(), "ExprNode_PathValue");
+ }
+ void visit(::HIR::ExprNode_Variable& node) override {
+ TODO(Span(), "ExprNode_Variable");
+ }
+
+ void visit(::HIR::ExprNode_StructLiteral& node) override {
+ TODO(Span(), "ExprNode_StructLiteral");
+ }
+ void visit(::HIR::ExprNode_Tuple& node) override {
+ TODO(Span(), "ExprNode_Tuple");
+ }
+ void visit(::HIR::ExprNode_ArrayList& node) override {
+ TODO(Span(), "ExprNode_ArrayList");
+ }
+ void visit(::HIR::ExprNode_ArraySized& node) override {
+ TODO(Span(), "ExprNode_ArraySized");
+ }
+
+ void visit(::HIR::ExprNode_Closure& node) override {
+ badnode(node);
+ }
+ };
+
+ Visitor v { crate };
+ expr.visit(v);
+
+ if( v.m_rv.is_Invalid() ) {
+ BUG(Span(), "Expression did not yeild a literal");
+ }
+
+ return mv$(v.m_rv);
+ }
+
+ class Expander:
+ public ::HIR::Visitor
+ {
+ const ::HIR::Crate& m_crate;
+
+ public:
+ Expander(const ::HIR::Crate& crate):
+ m_crate(crate)
+ {}
+
+ void visit_type(::HIR::TypeRef& ty)
+ {
+ 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);
+ )
+ else {
+ ::HIR::Visitor::visit_type(ty);
+ }
+ }
+ void visit_expr(::HIR::ExprPtr& expr) override
+ {
+ struct Visitor:
+ public ::HIR::ExprVisitorDef
+ {
+ const ::HIR::Crate& m_crate;
+
+ Visitor(const ::HIR::Crate& crate):
+ m_crate(crate)
+ {}
+
+ 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");
+ node.m_size_val = val.as_Integer();
+ }
+ };
+
+ if( &*expr != nullptr )
+ {
+ Visitor v { this->m_crate };
+ (*expr).visit(v);
+ }
+ }
+ };
+} // namespace
+
+void ConvertHIR_ConstantEvaluate(::HIR::Crate& crate)
{
+ Expander exp { crate };
+ exp.visit_crate( crate );
}