#ifndef QLOW_SEMANTIC_H #define QLOW_SEMANTIC_H #include #include #include "Util.h" #include "Ast.h" #include "Visitor.h" #include "Scope.h" #include "Type.h" #include #include #include namespace qlow { namespace sem { std::unique_ptr createFromAst(const std::vector>& objects); struct Class; struct Variable; struct Field; struct Method; struct Statement; struct Expression; struct DoEndBlock; struct IfElseBlock; struct WhileBlock; struct FeatureCallStatement; struct AssignmentStatement; struct ReturnStatement; struct LocalVariableExpression; struct Operation; struct UnaryOperation; struct BinaryOperation; struct CastExpression; struct NewArrayExpression; struct FeatureCallExpression; struct IntConst; } class ExpressionCodegenVisitor; class StatementVisitor; namespace gen { class FunctionGenerator; } } struct qlow::sem::Class : public SemanticObject { qlow::ast::Class* astNode; std::string name; SymbolTable fields; SymbolTable methods; ClassScope scope; /// \brief generated during llvm code generation, not availab llvm::Type* llvmType; inline Class(qlow::ast::Class* astNode, GlobalScope& globalScope) : astNode{ astNode }, name{ astNode->name }, scope{ globalScope, this }, llvmType{ nullptr } { } inline Class(const std::string& nativeName, GlobalScope& globalScope) : astNode{ nullptr }, name{ nativeName }, scope{ globalScope, this }, llvmType{ nullptr } { } virtual std::string toString(void) const override; }; struct qlow::sem::Variable : public SemanticObject { std::shared_ptr type; std::string name; /// if this is a local variable, this stores a reference to the llvm /// instance of this variable. If it is a parameter, the parameter value llvm::Value* allocaInst; Variable(void) = default; inline Variable(std::shared_ptr type, const std::string& name) : type{ std::move(type) }, name{ name }, allocaInst { nullptr } {} virtual std::string toString(void) const override; }; struct qlow::sem::Field : public Variable { virtual std::string toString(void) const override; }; struct qlow::sem::Method : public SemanticObject { Class* containingType; std::shared_ptr returnType; std::vector arguments; std::string name; ast::MethodDefinition* astNode; std::unique_ptr body; LocalScope scope; llvm::Function* llvmNode; inline Method(Scope& parentScope, std::shared_ptr returnType) : returnType{ std::move(returnType) }, scope{ parentScope }, body{ nullptr } { } inline Method(ast::MethodDefinition* astNode, Scope& parentScope) : astNode{ astNode }, name{ astNode->name }, scope{ parentScope }, body{ nullptr } { } virtual std::string toString(void) const override; }; struct qlow::sem::Statement : public SemanticObject, public Visitable { virtual llvm::Value* accept(qlow::StatementVisitor&, gen::FunctionGenerator&) = 0; }; struct qlow::sem::DoEndBlock : public Statement { LocalScope scope; OwningList statements; inline DoEndBlock(Scope& parentScope) : scope{ parentScope } {} virtual llvm::Value* accept(qlow::StatementVisitor&, gen::FunctionGenerator&) override; }; struct qlow::sem::IfElseBlock : public Statement { std::unique_ptr condition; std::unique_ptr ifBlock; std::unique_ptr elseBlock; inline IfElseBlock(std::unique_ptr condition, std::unique_ptr ifBlock, std::unique_ptr elseBlock) : condition{ std::move(condition) }, ifBlock{ std::move(ifBlock) }, elseBlock{ std::move(elseBlock) } { } virtual llvm::Value* accept(qlow::StatementVisitor&, gen::FunctionGenerator&) override; }; struct qlow::sem::WhileBlock : public Statement { std::unique_ptr condition; std::unique_ptr body; inline WhileBlock(std::unique_ptr condition, std::unique_ptr body) : condition{ std::move(condition) }, body{ std::move(body) } { } virtual llvm::Value* accept(qlow::StatementVisitor&, gen::FunctionGenerator&) override; }; struct qlow::sem::AssignmentStatement : public Statement { std::unique_ptr target; std::unique_ptr value; virtual std::string toString(void) const override; virtual llvm::Value* accept(qlow::StatementVisitor&, gen::FunctionGenerator&) override; }; struct qlow::sem::ReturnStatement : public Statement { std::unique_ptr value; virtual std::string toString(void) const override; virtual llvm::Value* accept(qlow::StatementVisitor&, gen::FunctionGenerator&) override; }; struct qlow::sem::Expression : public SemanticObject, public Visitable, qlow::ExpressionCodegenVisitor> { std::shared_ptr type; inline Expression(std::shared_ptr type) : type{ std::move(type) } { } }; struct qlow::sem::Operation : public Expression { std::string opString; inline Operation(std::shared_ptr type) : Expression{ std::move(type) } { } }; struct qlow::sem::LocalVariableExpression : public Expression { Variable* var; inline LocalVariableExpression(Variable* var) : Expression{ var->type }, var{ var } { } virtual llvm::Value* accept(ExpressionCodegenVisitor& visitor, llvm::IRBuilder<>& arg2) override; virtual std::string toString(void) const override; }; struct qlow::sem::BinaryOperation : public Operation { std::unique_ptr left; std::unique_ptr right; ast::BinaryOperation* astNode; /// method that is called to execute the operator sem::Method* operationMethod; inline BinaryOperation(std::shared_ptr type, ast::BinaryOperation* astNode) : Operation{ std::move(type) }, astNode{ astNode } { } virtual llvm::Value* accept(ExpressionCodegenVisitor& visitor, llvm::IRBuilder<>& arg2) override; virtual std::string toString(void) const override; }; struct qlow::sem::CastExpression : public Expression { std::unique_ptr expression; std::shared_ptr targetType; ast::CastExpression* astNode; inline CastExpression(std::unique_ptr expression, std::shared_ptr type, ast::CastExpression* astNode) : Expression{ type }, expression{ std::move(expression) }, targetType{ std::move(type) }, astNode{ astNode } { } virtual llvm::Value* accept(ExpressionCodegenVisitor& visitor, llvm::IRBuilder<>& arg2) override; virtual std::string toString(void) const override; }; struct qlow::sem::NewArrayExpression : public Expression { std::shared_ptr arrayType; std::unique_ptr length; inline NewArrayExpression(std::shared_ptr arrayType) : Expression{ std::make_shared(arrayType) }, arrayType{ std::move(arrayType) } { } virtual llvm::Value* accept(ExpressionCodegenVisitor& visitor, llvm::IRBuilder<>& arg2) override; virtual std::string toString(void) const override; }; struct qlow::sem::UnaryOperation : public Operation { qlow::ast::UnaryOperation::Side side; std::unique_ptr arg; inline UnaryOperation(std::shared_ptr type) : Operation{ std::move(type) } { } virtual llvm::Value* accept(ExpressionCodegenVisitor& visitor, llvm::IRBuilder<>& arg2) override; virtual std::string toString(void) const override; }; struct qlow::sem::FeatureCallExpression : public Expression { Method* callee; std::unique_ptr target; OwningList arguments; inline FeatureCallExpression(std::unique_ptr target, Method* callee) : Expression{ callee->returnType } { } virtual llvm::Value* accept(ExpressionCodegenVisitor& visitor, llvm::IRBuilder<>& arg2) override; virtual std::string toString(void) const override; }; struct qlow::sem::IntConst : public Expression { unsigned long long value; inline IntConst(unsigned long long value) : Expression{ std::make_shared(NativeType::INTEGER) }, value{ value } { } virtual llvm::Value* accept(ExpressionCodegenVisitor& visitor, llvm::IRBuilder<>& arg2) override; }; struct qlow::sem::FeatureCallStatement : public Statement { std::unique_ptr expr; inline FeatureCallStatement(std::unique_ptr expr) : expr{ std::move(expr) } {} virtual std::string toString(void) const override; virtual llvm::Value* accept(qlow::StatementVisitor&, gen::FunctionGenerator&) override; }; #endif // QLOW_SEMANTIC_H