├── .gitignore ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── ast ├── addition_expression.h ├── all.h ├── assignment_expression.h ├── block.h ├── bool_literal.h ├── division_expression.h ├── double_expression.h ├── dynamic_access_expression.h ├── dynamic_store_expression.h ├── equality_expression.h ├── expression.h ├── expression_statement.h ├── for_cond.h ├── func_call_expression.h ├── funcdecl.h ├── gt_expression.h ├── gte_expression.h ├── if_statement.h ├── inequality_expression.h ├── integer_expression.h ├── list_literal_expression.h ├── lt_expression.h ├── lte_expression.h ├── multiplication_expression.h ├── node.h ├── not_expression.h ├── pre_assignment_op.h ├── return_statement.h ├── statement.h ├── static_access_expression.h ├── static_store_expression.h ├── string_expression.h ├── subtraction_expression.h ├── var_decl.h ├── variable_expression.h ├── visitor.h └── void_literal.h ├── bench ├── bench.sh ├── fib_45.dart ├── fib_45.js ├── fib_45.vvn.sh ├── loop_empty.js ├── loop_empty_cc.vvn.sh ├── loop_empty_hot.vvn.sh ├── loop_empty_interp.vvn.sh ├── loop_with_function_cc.vvn.sh ├── loop_with_function_hot.vvn.sh ├── loop_with_function_interp.vvn.sh ├── loop_with_garbagemem.js ├── loop_with_garbagemem_cc.vvn.sh ├── loop_with_ops_cc.vvn.sh ├── loop_with_ops_hot.vvn.sh ├── loop_with_ops_interp.vvn.sh ├── lowest_common_factor.js ├── lowest_common_factor.vvn ├── recurse_with_ops.vvn.sh └── repeat_functions.vvn.sh ├── error_compiler.cpp ├── error_compiler.h ├── firstcompile.cpp ├── firstcompile.h ├── function_usage.h ├── functions.h ├── heap.cpp ├── heap.h ├── main.cpp ├── makefile ├── optimize.cpp ├── optimize.h ├── parser.cpp ├── parser.h ├── runtime_error.cpp ├── runtime_error.h ├── scope.h ├── ssa ├── cfg.h ├── common_subexpression.cpp ├── common_subexpression.h ├── constant_inliner.cpp ├── constant_inliner.h ├── constant_propagation.cpp ├── constant_propagation.h ├── dominator_builder.cpp ├── dominator_builder.h ├── emitter.cpp ├── emitter.h ├── forward_visitor.cpp ├── forward_visitor.h ├── function_merge.cpp ├── function_merge.h ├── inliner.cpp ├── inliner.h ├── instruction_combiner.cpp ├── instruction_combiner.h ├── jmp_threader.cpp ├── jmp_threader.h ├── loop_invariant.cpp ├── loop_invariant.h ├── print_visitor.cpp ├── print_visitor.h ├── reg_alloc.cpp ├── reg_alloc.h ├── ssa.cpp ├── ssa.h ├── type_analysis.cpp ├── type_analysis.h ├── unused_code.cpp └── unused_code.h ├── stack.cpp ├── stack.h ├── std.cpp ├── std.h ├── test ├── assemble │ ├── doubles.vvn │ ├── instruction_combiner.vvn │ ├── jmpcc.vvn │ ├── lists.vvn │ ├── modeq.vvn │ ├── objects.vvn │ └── strings.vvn ├── deoptimize │ ├── ints.vvn │ ├── ints.vvn_expectederrors │ ├── strings.vvn │ └── strings.vvn_expectederrors ├── error │ ├── interpret_type_errors.vvn │ └── interpret_type_errors.vvn_expectederrors ├── interpret │ ├── doubles.vvn │ ├── lists.vvn │ ├── modeq.vvn │ ├── objects.vvn │ └── strings.vvn ├── parser │ ├── comments_test.vvn │ ├── control_flow.vvn │ ├── functions_test.vvn │ ├── fuzz_test.vvn │ ├── fuzz_test.vvn_expectederrors │ ├── fuzz_test_generate.js │ ├── onliner.vvn │ ├── recovery_test.vvn │ ├── recovery_test.vvn_expectederrors │ ├── strings.vvn │ └── terms.vvn ├── run.sh └── std │ ├── lists_test.vvn │ ├── objects_test.vvn │ └── strings_test.vvn ├── tokenizer.cpp ├── tokenizer.h ├── type_info.h ├── ui_runtime ├── app.cpp ├── matrix.cpp ├── matrix.h ├── styled_char.cpp └── styled_char.h ├── util.h ├── value.cpp ├── value.h └── visitor ├── assignment_producer.cpp ├── assignment_producer.h ├── interpreter.cpp ├── interpreter.h ├── print_visitor.cpp ├── print_visitor.h ├── ssa_builder.cpp └── ssa_builder.h /.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | vvn 3 | *.swp 4 | *.dSYM 5 | bench/bench_log* 6 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # How to contribute 2 | 3 | We'd love to accept your patches and contributions to this project. There are 4 | just a few small guidelines you need to follow. 5 | 6 | ## Contributor License Agreement 7 | 8 | Contributions to this project must be accompanied by a Contributor License 9 | Agreement. You (or your employer) retain the copyright to your contribution, 10 | this simply gives us permission to use and redistribute your contributions as 11 | part of the project. Head over to to see 12 | your current agreements on file or to sign a new one. 13 | 14 | You generally only need to submit a CLA once, so if you've already submitted one 15 | (even if it was for a different project), you probably don't need to do it 16 | again. 17 | 18 | ## Code reviews 19 | 20 | All submissions, including submissions by project members, require review. We 21 | use GitHub pull requests for this purpose. Consult 22 | [GitHub Help](https://help.github.com/articles/about-pull-requests/) for more 23 | information on using pull requests. 24 | -------------------------------------------------------------------------------- /ast/addition_expression.h: -------------------------------------------------------------------------------- 1 | #ifndef VAIVEN_AST_HEADER_ADDITION_EXPRESSION 2 | #define VAIVEN_AST_HEADER_ADDITION_EXPRESSION 3 | 4 | #include 5 | #include "expression.h" 6 | 7 | using std::unique_ptr; 8 | 9 | namespace vaiven { namespace ast { 10 | 11 | template 12 | class AdditionExpression : public Expression { 13 | 14 | public: 15 | AdditionExpression( 16 | unique_ptr > left, 17 | unique_ptr > right) 18 | : left(std::move(left)), right(std::move(right)) {}; 19 | 20 | void accept(Visitor& v) { 21 | return v.visitAdditionExpression(*this); 22 | } 23 | virtual ~AdditionExpression() {}; 24 | 25 | unique_ptr > left; 26 | unique_ptr > right; 27 | }; 28 | 29 | }} 30 | 31 | #endif 32 | -------------------------------------------------------------------------------- /ast/all.h: -------------------------------------------------------------------------------- 1 | #include "expression.h" 2 | #include "addition_expression.h" 3 | #include "assignment_expression.h" 4 | #include "subtraction_expression.h" 5 | #include "multiplication_expression.h" 6 | #include "division_expression.h" 7 | #include "integer_expression.h" 8 | #include "double_expression.h" 9 | #include "string_expression.h" 10 | #include "variable_expression.h" 11 | #include "bool_literal.h" 12 | #include "void_literal.h" 13 | #include "not_expression.h" 14 | #include "equality_expression.h" 15 | #include "inequality_expression.h" 16 | #include "gt_expression.h" 17 | #include "gte_expression.h" 18 | #include "lt_expression.h" 19 | #include "lte_expression.h" 20 | #include "statement.h" 21 | #include "expression_statement.h" 22 | #include "block.h" 23 | #include "funcdecl.h" 24 | #include "func_call_expression.h" 25 | #include "list_literal_expression.h" 26 | #include "dynamic_access_expression.h" 27 | #include "dynamic_store_expression.h" 28 | #include "static_access_expression.h" 29 | #include "static_store_expression.h" 30 | #include "var_decl.h" 31 | #include "if_statement.h" 32 | #include "for_cond.h" 33 | #include "return_statement.h" 34 | -------------------------------------------------------------------------------- /ast/assignment_expression.h: -------------------------------------------------------------------------------- 1 | #ifndef VAIVEN_AST_HEADER_ASSIGNMENT_EXPRESSION 2 | #define VAIVEN_AST_HEADER_ASSIGNMENT_EXPRESSION 3 | 4 | #include 5 | #include 6 | #include "expression.h" 7 | #include "pre_assignment_op.h" 8 | 9 | using std::unique_ptr; 10 | using std::string; 11 | 12 | namespace vaiven { namespace ast { 13 | 14 | template 15 | class AssignmentExpression : public Expression { 16 | 17 | public: 18 | AssignmentExpression( 19 | string varname, unique_ptr > expr, 20 | PreAssignmentOp preAssignmentOp) 21 | : varname(varname), expr(std::move(expr)), preAssignmentOp(preAssignmentOp) {}; 22 | 23 | void accept(Visitor& v) { 24 | return v.visitAssignmentExpression(*this); 25 | } 26 | virtual ~AssignmentExpression() {}; 27 | 28 | string varname; 29 | unique_ptr > expr; 30 | PreAssignmentOp preAssignmentOp; 31 | }; 32 | 33 | }} 34 | 35 | #endif 36 | -------------------------------------------------------------------------------- /ast/block.h: -------------------------------------------------------------------------------- 1 | #ifndef VAIVEN_AST_HEADER_BLOCK 2 | #define VAIVEN_AST_HEADER_BLOCK 3 | 4 | #include 5 | #include 6 | #include "statement.h" 7 | 8 | using std::unique_ptr; 9 | using std::vector; 10 | 11 | namespace vaiven { namespace ast { 12 | 13 | template 14 | class Block : public Statement { 15 | 16 | public: 17 | Block( 18 | vector > > statements) 19 | : statements(std::move(statements)) {}; 20 | 21 | void accept(Visitor& v) { 22 | return v.visitBlock(*this); 23 | } 24 | virtual ~Block() {}; 25 | 26 | vector > > statements; 27 | }; 28 | 29 | }} 30 | 31 | #endif 32 | -------------------------------------------------------------------------------- /ast/bool_literal.h: -------------------------------------------------------------------------------- 1 | #ifndef VAIVEN_AST_HEADER_BOOL_LITERAL 2 | #define VAIVEN_AST_HEADER_BOOL_LITERAL 3 | 4 | #include 5 | #include "expression.h" 6 | 7 | using std::unique_ptr; 8 | 9 | namespace vaiven { namespace ast { 10 | 11 | template 12 | class BoolLiteral : public Expression { 13 | 14 | public: 15 | BoolLiteral(bool value) : value(value) {}; 16 | 17 | void accept(Visitor& v) { 18 | return v.visitBoolLiteral(*this); 19 | } 20 | virtual ~BoolLiteral() {}; 21 | 22 | bool value; 23 | }; 24 | 25 | }} 26 | 27 | #endif 28 | -------------------------------------------------------------------------------- /ast/division_expression.h: -------------------------------------------------------------------------------- 1 | #ifndef VAIVEN_AST_HEADER_DIVISION_EXPRESSION 2 | #define VAIVEN_AST_HEADER_DIVISION_EXPRESSION 3 | 4 | #include 5 | #include "expression.h" 6 | 7 | using std::unique_ptr; 8 | 9 | namespace vaiven { namespace ast { 10 | 11 | template 12 | class DivisionExpression : public Expression { 13 | 14 | public: 15 | DivisionExpression( 16 | unique_ptr > left, 17 | unique_ptr > right) 18 | : left(std::move(left)), right(std::move(right)) {}; 19 | 20 | void accept(Visitor& v) { 21 | return v.visitDivisionExpression(*this); 22 | } 23 | virtual ~DivisionExpression() {}; 24 | 25 | unique_ptr > left; 26 | unique_ptr > right; 27 | }; 28 | 29 | }} 30 | 31 | #endif 32 | -------------------------------------------------------------------------------- /ast/double_expression.h: -------------------------------------------------------------------------------- 1 | #ifndef VAIVEN_AST_HEADER_DOUBLE_EXPRESSION 2 | #define VAIVEN_AST_HEADER_DOUBLE_EXPRESSION 3 | 4 | #include 5 | #include "expression.h" 6 | 7 | using std::unique_ptr; 8 | 9 | namespace vaiven { namespace ast { 10 | 11 | template 12 | class DoubleExpression : public Expression { 13 | 14 | public: 15 | DoubleExpression(double value) : value(value) {}; 16 | 17 | void accept(Visitor& v) { 18 | return v.visitDoubleExpression(*this); 19 | } 20 | virtual ~DoubleExpression() {}; 21 | 22 | double value; 23 | }; 24 | 25 | }} 26 | 27 | #endif 28 | -------------------------------------------------------------------------------- /ast/dynamic_access_expression.h: -------------------------------------------------------------------------------- 1 | #ifndef VAIVEN_AST_HEADER_DYNAMIC_ACCESS_EXPRESSION 2 | #define VAIVEN_AST_HEADER_DYNAMIC_ACCESS_EXPRESSION 3 | 4 | #include 5 | #include "expression.h" 6 | 7 | using std::unique_ptr; 8 | 9 | namespace vaiven { namespace ast { 10 | 11 | template 12 | class DynamicAccessExpression : public Expression { 13 | 14 | public: 15 | DynamicAccessExpression( 16 | unique_ptr > subject, 17 | unique_ptr > property) 18 | : subject(std::move(subject)), property(std::move(property)) {}; 19 | 20 | void accept(Visitor& v) { 21 | return v.visitDynamicAccessExpression(*this); 22 | } 23 | virtual ~DynamicAccessExpression() {}; 24 | 25 | unique_ptr > subject; 26 | unique_ptr > property; 27 | }; 28 | 29 | }} 30 | 31 | #endif 32 | -------------------------------------------------------------------------------- /ast/dynamic_store_expression.h: -------------------------------------------------------------------------------- 1 | #ifndef VAIVEN_AST_HEADER_DYNAMIC_STORE_EXPRESSION 2 | #define VAIVEN_AST_HEADER_DYNAMIC_STORE_EXPRESSION 3 | 4 | #include 5 | #include 6 | #include "expression.h" 7 | #include "pre_assignment_op.h" 8 | 9 | using std::unique_ptr; 10 | using std::string; 11 | 12 | namespace vaiven { namespace ast { 13 | 14 | template 15 | class DynamicStoreExpression : public Expression { 16 | 17 | public: 18 | DynamicStoreExpression( 19 | unique_ptr > subject, 20 | unique_ptr > property, 21 | unique_ptr > rhs, 22 | PreAssignmentOp preAssignmentOp) 23 | : property(std::move(property)), subject(std::move(subject)), rhs(std::move(rhs)), preAssignmentOp(preAssignmentOp) {}; 24 | 25 | void accept(Visitor& v) { 26 | return v.visitDynamicStoreExpression(*this); 27 | } 28 | virtual ~DynamicStoreExpression() {}; 29 | 30 | unique_ptr > subject; 31 | unique_ptr > property; 32 | unique_ptr > rhs; 33 | PreAssignmentOp preAssignmentOp; 34 | }; 35 | 36 | }} 37 | 38 | #endif 39 | -------------------------------------------------------------------------------- /ast/equality_expression.h: -------------------------------------------------------------------------------- 1 | #ifndef VAIVEN_AST_HEADER_EQUALITY_EXPRESSION 2 | #define VAIVEN_AST_HEADER_EQUALITY_EXPRESSION 3 | 4 | #include 5 | #include "expression.h" 6 | 7 | using std::unique_ptr; 8 | 9 | namespace vaiven { namespace ast { 10 | 11 | template 12 | class EqualityExpression : public Expression { 13 | 14 | public: 15 | EqualityExpression( 16 | unique_ptr > left, 17 | unique_ptr > right) 18 | : left(std::move(left)), right(std::move(right)) {}; 19 | 20 | void accept(Visitor& v) { 21 | return v.visitEqualityExpression(*this); 22 | } 23 | virtual ~EqualityExpression() {}; 24 | 25 | unique_ptr > left; 26 | unique_ptr > right; 27 | }; 28 | 29 | }} 30 | 31 | #endif 32 | -------------------------------------------------------------------------------- /ast/expression.h: -------------------------------------------------------------------------------- 1 | #ifndef VAIVEN_AST_HEADER_EXPRESSION 2 | #define VAIVEN_AST_HEADER_EXPRESSION 3 | 4 | #include "node.h" 5 | 6 | namespace vaiven { namespace ast { 7 | 8 | // nothing yet 9 | template 10 | class Expression : public Node { 11 | public: 12 | virtual ~Expression() {}; 13 | }; 14 | 15 | }} 16 | 17 | #endif 18 | -------------------------------------------------------------------------------- /ast/expression_statement.h: -------------------------------------------------------------------------------- 1 | #ifndef VAIVEN_AST_HEADER_EXPRESSION_STATEMENT 2 | #define VAIVEN_AST_HEADER_EXPRESSION_STATEMENT 3 | 4 | #include 5 | #include "statement.h" 6 | 7 | using std::unique_ptr; 8 | 9 | namespace vaiven { namespace ast { 10 | 11 | template 12 | class ExpressionStatement : public Statement { 13 | 14 | public: 15 | ExpressionStatement( 16 | unique_ptr > expr) 17 | : expr(std::move(expr)) {}; 18 | 19 | void accept(Visitor& v) { 20 | return v.visitExpressionStatement(*this); 21 | } 22 | virtual ~ExpressionStatement() {}; 23 | 24 | unique_ptr > expr; 25 | }; 26 | 27 | }} 28 | 29 | #endif 30 | -------------------------------------------------------------------------------- /ast/for_cond.h: -------------------------------------------------------------------------------- 1 | #ifndef VAIVEN_AST_HEADER_FOR_COND 2 | #define VAIVEN_AST_HEADER_FOR_COND 3 | 4 | #include 5 | #include 6 | #include "statement.h" 7 | #include "expression.h" 8 | 9 | using std::unique_ptr; 10 | using std::vector; 11 | 12 | namespace vaiven { namespace ast { 13 | 14 | template 15 | class ForCondition : public Statement { 16 | 17 | public: 18 | ForCondition( 19 | unique_ptr > condition, 20 | vector > > statements) 21 | : condition(std::move(condition)) 22 | , statements(std::move(statements)) {}; 23 | 24 | void accept(Visitor& v) { 25 | return v.visitForCondition(*this); 26 | } 27 | virtual ~ForCondition() {}; 28 | 29 | unique_ptr > condition; 30 | vector > > statements; 31 | }; 32 | 33 | }} 34 | 35 | #endif 36 | -------------------------------------------------------------------------------- /ast/func_call_expression.h: -------------------------------------------------------------------------------- 1 | #ifndef VAIVEN_AST_HEADER_FUNC_CALL_EXPRESSION 2 | #define VAIVEN_AST_HEADER_FUNC_CALL_EXPRESSION 3 | 4 | #include 5 | #include 6 | #include 7 | #include "expression.h" 8 | 9 | using std::unique_ptr; 10 | using std::vector; 11 | using std::string; 12 | 13 | namespace vaiven { namespace ast { 14 | 15 | template 16 | class FuncCallExpression : public Expression { 17 | 18 | public: 19 | FuncCallExpression(string name, vector > > parameters) : 20 | name(name), 21 | parameters(std::move(parameters)) {}; 22 | 23 | void accept(Visitor& v) { 24 | return v.visitFuncCallExpression(*this); 25 | } 26 | virtual ~FuncCallExpression() {}; 27 | 28 | vector > > parameters; 29 | string name; 30 | }; 31 | 32 | }} 33 | 34 | #endif 35 | -------------------------------------------------------------------------------- /ast/funcdecl.h: -------------------------------------------------------------------------------- 1 | #ifndef VAIVEN_AST_HEADER_FUNCDECL 2 | #define VAIVEN_AST_HEADER_FUNCDECL 3 | 4 | #include 5 | #include 6 | #include 7 | #include "statement.h" 8 | 9 | using std::unique_ptr; 10 | using std::vector; 11 | using std::string; 12 | 13 | namespace vaiven { namespace ast { 14 | 15 | template 16 | class FuncDecl : public Node { 17 | 18 | public: 19 | FuncDecl( 20 | string name, 21 | vector args, 22 | vector > > statements) 23 | : statements(std::move(statements)), name(name), args(args) {}; 24 | 25 | void accept(Visitor& v) { 26 | return v.visitFuncDecl(*this); 27 | } 28 | virtual ~FuncDecl() {}; 29 | 30 | string name; 31 | vector > > statements; 32 | vector args; 33 | }; 34 | 35 | }} 36 | 37 | #endif 38 | -------------------------------------------------------------------------------- /ast/gt_expression.h: -------------------------------------------------------------------------------- 1 | #ifndef VAIVEN_AST_HEADER_GT_EXPRESSION 2 | #define VAIVEN_AST_HEADER_GT_EXPRESSION 3 | 4 | #include 5 | #include "expression.h" 6 | 7 | using std::unique_ptr; 8 | 9 | namespace vaiven { namespace ast { 10 | 11 | template 12 | class GtExpression : public Expression { 13 | 14 | public: 15 | GtExpression( 16 | unique_ptr > left, 17 | unique_ptr > right) 18 | : left(std::move(left)), right(std::move(right)) {}; 19 | 20 | void accept(Visitor& v) { 21 | return v.visitGtExpression(*this); 22 | } 23 | virtual ~GtExpression() {}; 24 | 25 | unique_ptr > left; 26 | unique_ptr > right; 27 | }; 28 | 29 | }} 30 | 31 | #endif 32 | -------------------------------------------------------------------------------- /ast/gte_expression.h: -------------------------------------------------------------------------------- 1 | #ifndef VAIVEN_AST_HEADER_GTE_EXPRESSION 2 | #define VAIVEN_AST_HEADER_GTE_EXPRESSION 3 | 4 | #include 5 | #include "expression.h" 6 | 7 | using std::unique_ptr; 8 | 9 | namespace vaiven { namespace ast { 10 | 11 | template 12 | class GteExpression : public Expression { 13 | 14 | public: 15 | GteExpression( 16 | unique_ptr > left, 17 | unique_ptr > right) 18 | : left(std::move(left)), right(std::move(right)) {}; 19 | 20 | void accept(Visitor& v) { 21 | return v.visitGteExpression(*this); 22 | } 23 | virtual ~GteExpression() {}; 24 | 25 | unique_ptr > left; 26 | unique_ptr > right; 27 | }; 28 | 29 | }} 30 | 31 | #endif 32 | -------------------------------------------------------------------------------- /ast/if_statement.h: -------------------------------------------------------------------------------- 1 | #ifndef VAIVEN_AST_HEADER_IF_STATEMENT 2 | #define VAIVEN_AST_HEADER_IF_STATEMENT 3 | 4 | #include 5 | #include 6 | #include "statement.h" 7 | #include "expression.h" 8 | 9 | using std::unique_ptr; 10 | using std::vector; 11 | 12 | namespace vaiven { namespace ast { 13 | 14 | template 15 | class IfStatement : public Statement { 16 | 17 | public: 18 | IfStatement( 19 | unique_ptr > condition, 20 | vector > > trueStatements, 21 | vector > > falseStatements) 22 | : condition(std::move(condition)) 23 | , trueStatements(std::move(trueStatements)) 24 | , falseStatements(std::move(falseStatements)) {}; 25 | 26 | void accept(Visitor& v) { 27 | return v.visitIfStatement(*this); 28 | } 29 | virtual ~IfStatement() {}; 30 | 31 | unique_ptr > condition; 32 | vector > > trueStatements; 33 | vector > > falseStatements; 34 | }; 35 | 36 | }} 37 | 38 | #endif 39 | -------------------------------------------------------------------------------- /ast/inequality_expression.h: -------------------------------------------------------------------------------- 1 | #ifndef VAIVEN_AST_HEADER_INEQUALITY_EXPRESSION 2 | #define VAIVEN_AST_HEADER_INEQUALITY_EXPRESSION 3 | 4 | #include 5 | #include "expression.h" 6 | 7 | using std::unique_ptr; 8 | 9 | namespace vaiven { namespace ast { 10 | 11 | template 12 | class InequalityExpression : public Expression { 13 | 14 | public: 15 | InequalityExpression( 16 | unique_ptr > left, 17 | unique_ptr > right) 18 | : left(std::move(left)), right(std::move(right)) {}; 19 | 20 | void accept(Visitor& v) { 21 | return v.visitInequalityExpression(*this); 22 | } 23 | virtual ~InequalityExpression() {}; 24 | 25 | unique_ptr > left; 26 | unique_ptr > right; 27 | }; 28 | 29 | }} 30 | 31 | #endif 32 | -------------------------------------------------------------------------------- /ast/integer_expression.h: -------------------------------------------------------------------------------- 1 | #ifndef VAIVEN_AST_HEADER_INTEGER_EXPRESSION 2 | #define VAIVEN_AST_HEADER_INTEGER_EXPRESSION 3 | 4 | #include 5 | #include "expression.h" 6 | 7 | using std::unique_ptr; 8 | 9 | namespace vaiven { namespace ast { 10 | 11 | template 12 | class IntegerExpression : public Expression { 13 | 14 | public: 15 | IntegerExpression(int value) : value(value) {}; 16 | 17 | void accept(Visitor& v) { 18 | return v.visitIntegerExpression(*this); 19 | } 20 | virtual ~IntegerExpression() {}; 21 | 22 | int value; 23 | }; 24 | 25 | }} 26 | 27 | #endif 28 | -------------------------------------------------------------------------------- /ast/list_literal_expression.h: -------------------------------------------------------------------------------- 1 | #ifndef VAIVEN_AST_HEADER_LIST_LITERAL_EXPRESSION 2 | #define VAIVEN_AST_HEADER_LIST_LITERAL_EXPRESSION 3 | 4 | #include 5 | #include 6 | #include 7 | #include "expression.h" 8 | 9 | using std::unique_ptr; 10 | using std::vector; 11 | using std::string; 12 | 13 | namespace vaiven { namespace ast { 14 | 15 | template 16 | class ListLiteralExpression : public Expression { 17 | 18 | public: 19 | ListLiteralExpression(vector > > items) : 20 | items(std::move(items)) {}; 21 | 22 | void accept(Visitor& v) { 23 | return v.visitListLiteralExpression(*this); 24 | } 25 | virtual ~ListLiteralExpression() {}; 26 | 27 | vector > > items; 28 | }; 29 | 30 | }} 31 | 32 | #endif 33 | -------------------------------------------------------------------------------- /ast/lt_expression.h: -------------------------------------------------------------------------------- 1 | #ifndef VAIVEN_AST_HEADER_LT_EXPRESSION 2 | #define VAIVEN_AST_HEADER_LT_EXPRESSION 3 | 4 | #include 5 | #include "expression.h" 6 | 7 | using std::unique_ptr; 8 | 9 | namespace vaiven { namespace ast { 10 | 11 | template 12 | class LtExpression : public Expression { 13 | 14 | public: 15 | LtExpression( 16 | unique_ptr > left, 17 | unique_ptr > right) 18 | : left(std::move(left)), right(std::move(right)) {}; 19 | 20 | void accept(Visitor& v) { 21 | return v.visitLtExpression(*this); 22 | } 23 | virtual ~LtExpression() {}; 24 | 25 | unique_ptr > left; 26 | unique_ptr > right; 27 | }; 28 | 29 | }} 30 | 31 | #endif 32 | -------------------------------------------------------------------------------- /ast/lte_expression.h: -------------------------------------------------------------------------------- 1 | #ifndef VAIVEN_AST_HEADER_LTE_EXPRESSION 2 | #define VAIVEN_AST_HEADER_LTE_EXPRESSION 3 | 4 | #include 5 | #include "expression.h" 6 | 7 | using std::unique_ptr; 8 | 9 | namespace vaiven { namespace ast { 10 | 11 | template 12 | class LteExpression : public Expression { 13 | 14 | public: 15 | LteExpression( 16 | unique_ptr > left, 17 | unique_ptr > right) 18 | : left(std::move(left)), right(std::move(right)) {}; 19 | 20 | void accept(Visitor& v) { 21 | return v.visitLteExpression(*this); 22 | } 23 | virtual ~LteExpression() {}; 24 | 25 | unique_ptr > left; 26 | unique_ptr > right; 27 | }; 28 | 29 | }} 30 | 31 | #endif 32 | -------------------------------------------------------------------------------- /ast/multiplication_expression.h: -------------------------------------------------------------------------------- 1 | #ifndef VAIVEN_AST_HEADER_MULTIPLICATION_EXPRESSION 2 | #define VAIVEN_AST_HEADER_MULTIPLICATION_EXPRESSION 3 | 4 | #include 5 | #include "expression.h" 6 | 7 | using std::unique_ptr; 8 | 9 | namespace vaiven { namespace ast { 10 | 11 | template 12 | class MultiplicationExpression : public Expression { 13 | 14 | public: 15 | MultiplicationExpression( 16 | unique_ptr > left, 17 | unique_ptr > right) 18 | : left(std::move(left)), right(std::move(right)) {}; 19 | 20 | void accept(Visitor& v) { 21 | return v.visitMultiplicationExpression(*this); 22 | } 23 | virtual ~MultiplicationExpression() {}; 24 | 25 | unique_ptr > left; 26 | unique_ptr > right; 27 | }; 28 | 29 | }} 30 | 31 | #endif 32 | -------------------------------------------------------------------------------- /ast/node.h: -------------------------------------------------------------------------------- 1 | #ifndef VAIVEN_AST_HEADER_NODE 2 | #define VAIVEN_AST_HEADER_NODE 3 | 4 | #include "visitor.h" 5 | 6 | namespace vaiven { namespace ast { 7 | 8 | template 9 | class Node { 10 | public: 11 | virtual void accept(Visitor& v)=0; 12 | virtual ~Node() {}; 13 | 14 | RD resolvedData; 15 | }; 16 | 17 | // save space on Node<> 18 | template<> 19 | class Node { 20 | public: 21 | virtual void accept(Visitor<>& v)=0; 22 | virtual ~Node() {}; 23 | }; 24 | 25 | 26 | }} 27 | 28 | #endif 29 | -------------------------------------------------------------------------------- /ast/not_expression.h: -------------------------------------------------------------------------------- 1 | #ifndef VAIVEN_AST_HEADER_NOT_EXPRESSION 2 | #define VAIVEN_AST_HEADER_NOT_EXPRESSION 3 | 4 | #include 5 | #include "expression.h" 6 | 7 | using std::unique_ptr; 8 | 9 | namespace vaiven { namespace ast { 10 | 11 | template 12 | class NotExpression : public Expression { 13 | 14 | public: 15 | NotExpression(unique_ptr > expr) : expr(std::move(expr)) {}; 16 | 17 | void accept(Visitor& v) { 18 | return v.visitNotExpression(*this); 19 | } 20 | virtual ~NotExpression() {}; 21 | 22 | unique_ptr > expr; 23 | }; 24 | 25 | }} 26 | 27 | #endif 28 | -------------------------------------------------------------------------------- /ast/pre_assignment_op.h: -------------------------------------------------------------------------------- 1 | // Copyright 2017 Google Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #ifndef VAIVEN_AST_HEADER_PRE_ASSIGNMENT_OP 16 | #define VAIVEN_AST_HEADER_PRE_ASSIGNMENT_OP 17 | 18 | namespace vaiven { namespace ast { 19 | 20 | enum PreAssignmentOp { 21 | kPreAssignmentOpNone, 22 | kPreAssignmentOpAdd, 23 | kPreAssignmentOpSub, 24 | kPreAssignmentOpMul, 25 | kPreAssignmentOpDiv, 26 | }; 27 | 28 | } } 29 | 30 | #endif 31 | -------------------------------------------------------------------------------- /ast/return_statement.h: -------------------------------------------------------------------------------- 1 | #ifndef VAIVEN_AST_HEADER_RETURN_STATEMENT 2 | #define VAIVEN_AST_HEADER_RETURN_STATEMENT 3 | 4 | #include 5 | #include "statement.h" 6 | 7 | using std::unique_ptr; 8 | 9 | namespace vaiven { namespace ast { 10 | 11 | template 12 | class ReturnStatement : public Statement { 13 | 14 | public: 15 | ReturnStatement( 16 | unique_ptr > expr) 17 | : expr(std::move(expr)) {}; 18 | 19 | void accept(Visitor& v) { 20 | return v.visitReturnStatement(*this); 21 | } 22 | virtual ~ReturnStatement() {}; 23 | 24 | unique_ptr > expr; 25 | }; 26 | 27 | }} 28 | 29 | #endif 30 | -------------------------------------------------------------------------------- /ast/statement.h: -------------------------------------------------------------------------------- 1 | #ifndef VAIVEN_AST_HEADER_STATEMENT 2 | #define VAIVEN_AST_HEADER_STATEMENT 3 | 4 | #include "node.h" 5 | 6 | namespace vaiven { namespace ast { 7 | 8 | // nothing yet 9 | template 10 | class Statement : public Node { 11 | public: 12 | virtual ~Statement() {}; 13 | }; 14 | 15 | }} 16 | 17 | #endif 18 | -------------------------------------------------------------------------------- /ast/static_access_expression.h: -------------------------------------------------------------------------------- 1 | #ifndef VAIVEN_AST_HEADER_STATIC_ACCESS_EXPRESSION 2 | #define VAIVEN_AST_HEADER_STATIC_ACCESS_EXPRESSION 3 | 4 | #include 5 | #include 6 | #include "expression.h" 7 | 8 | using std::unique_ptr; 9 | using std::string; 10 | 11 | namespace vaiven { namespace ast { 12 | 13 | template 14 | class StaticAccessExpression : public Expression { 15 | 16 | public: 17 | StaticAccessExpression( 18 | unique_ptr > subject, 19 | string property) 20 | : subject(std::move(subject)), property(property) {}; 21 | 22 | void accept(Visitor& v) { 23 | return v.visitStaticAccessExpression(*this); 24 | } 25 | virtual ~StaticAccessExpression() {}; 26 | 27 | unique_ptr > subject; 28 | string property; 29 | }; 30 | 31 | }} 32 | 33 | #endif 34 | -------------------------------------------------------------------------------- /ast/static_store_expression.h: -------------------------------------------------------------------------------- 1 | #ifndef VAIVEN_AST_HEADER_STATIC_STORE_EXPRESSION 2 | #define VAIVEN_AST_HEADER_STATIC_STORE_EXPRESSION 3 | 4 | #include 5 | #include 6 | #include "expression.h" 7 | #include "pre_assignment_op.h" 8 | 9 | using std::unique_ptr; 10 | using std::string; 11 | 12 | namespace vaiven { namespace ast { 13 | 14 | template 15 | class StaticStoreExpression : public Expression { 16 | 17 | public: 18 | StaticStoreExpression( 19 | unique_ptr > subject, 20 | string property, 21 | unique_ptr > rhs, 22 | PreAssignmentOp preAssignmentOp) 23 | : subject(std::move(subject)), property(property), rhs(std::move(rhs)), preAssignmentOp(preAssignmentOp) {}; 24 | 25 | void accept(Visitor& v) { 26 | return v.visitStaticStoreExpression(*this); 27 | } 28 | virtual ~StaticStoreExpression() {}; 29 | 30 | unique_ptr > subject; 31 | string property; 32 | unique_ptr > rhs; 33 | PreAssignmentOp preAssignmentOp; 34 | }; 35 | 36 | }} 37 | 38 | #endif 39 | -------------------------------------------------------------------------------- /ast/string_expression.h: -------------------------------------------------------------------------------- 1 | #ifndef VAIVEN_AST_HEADER_STRING_EXPRESSION 2 | #define VAIVEN_AST_HEADER_STRING_EXPRESSION 3 | 4 | #include 5 | #include "expression.h" 6 | #include "../heap.h" 7 | 8 | using std::unique_ptr; 9 | 10 | namespace vaiven { namespace ast { 11 | 12 | template 13 | class StringExpression : public Expression { 14 | 15 | public: 16 | StringExpression(GcableString* value) : value(value) {}; 17 | virtual ~StringExpression() { 18 | if (globalHeap == NULL) { 19 | delete value; 20 | } else { 21 | globalHeap->owned_ptrs.insert(value); 22 | } 23 | } 24 | 25 | void accept(Visitor& v) { 26 | return v.visitStringExpression(*this); 27 | } 28 | 29 | GcableString* value; 30 | }; 31 | 32 | }} 33 | 34 | #endif 35 | -------------------------------------------------------------------------------- /ast/subtraction_expression.h: -------------------------------------------------------------------------------- 1 | #ifndef VAIVEN_AST_HEADER_SUBTRACTION_EXPRESSION 2 | #define VAIVEN_AST_HEADER_SUBTRACTION_EXPRESSION 3 | 4 | #include 5 | #include "expression.h" 6 | 7 | using std::unique_ptr; 8 | 9 | namespace vaiven { namespace ast { 10 | 11 | template 12 | class SubtractionExpression : public Expression { 13 | 14 | public: 15 | SubtractionExpression( 16 | unique_ptr > left, 17 | unique_ptr > right) 18 | : left(std::move(left)), right(std::move(right)) {}; 19 | 20 | void accept(Visitor& v) { 21 | return v.visitSubtractionExpression(*this); 22 | } 23 | virtual ~SubtractionExpression() {}; 24 | 25 | unique_ptr > left; 26 | unique_ptr > right; 27 | }; 28 | 29 | }} 30 | 31 | #endif 32 | -------------------------------------------------------------------------------- /ast/var_decl.h: -------------------------------------------------------------------------------- 1 | #ifndef VAIVEN_AST_HEADER_VAR_DECL 2 | #define VAIVEN_AST_HEADER_VAR_DECL 3 | 4 | #include 5 | #include 6 | #include "statement.h" 7 | 8 | using std::unique_ptr; 9 | using std::string; 10 | 11 | namespace vaiven { namespace ast { 12 | 13 | template 14 | class VarDecl : public Statement { 15 | 16 | public: 17 | VarDecl( 18 | string varname, unique_ptr > expr) 19 | : varname(varname), expr(std::move(expr)) {}; 20 | 21 | void accept(Visitor& v) { 22 | return v.visitVarDecl(*this); 23 | } 24 | virtual ~VarDecl() {}; 25 | 26 | unique_ptr > expr; 27 | string varname; 28 | }; 29 | 30 | }} 31 | 32 | #endif 33 | -------------------------------------------------------------------------------- /ast/variable_expression.h: -------------------------------------------------------------------------------- 1 | #ifndef VAIVEN_AST_HEADER_VARIABLE_EXPRESSION 2 | #define VAIVEN_AST_HEADER_VARIABLE_EXPRESSION 3 | 4 | #include 5 | #include "expression.h" 6 | 7 | using std::string; 8 | 9 | namespace vaiven { namespace ast { 10 | 11 | template 12 | class VariableExpression : public Expression { 13 | 14 | public: 15 | VariableExpression(string id) : id(id) {}; 16 | 17 | void accept(Visitor& v) { 18 | return v.visitVariableExpression(*this); 19 | } 20 | virtual ~VariableExpression() {}; 21 | 22 | string id; 23 | }; 24 | 25 | }} 26 | 27 | #endif 28 | -------------------------------------------------------------------------------- /ast/visitor.h: -------------------------------------------------------------------------------- 1 | #ifndef VAIVEN_AST_HEADER_VISITOR 2 | #define VAIVEN_AST_HEADER_VISITOR 3 | 4 | namespace vaiven { namespace ast { 5 | 6 | template 7 | class Node; 8 | template 9 | class AssignmentExpression; 10 | template 11 | class AdditionExpression; 12 | template 13 | class SubtractionExpression; 14 | template 15 | class MultiplicationExpression; 16 | template 17 | class DivisionExpression; 18 | template 19 | class IntegerExpression; 20 | template 21 | class DoubleExpression; 22 | template 23 | class StringExpression; 24 | template 25 | class VariableExpression; 26 | template 27 | class BoolLiteral; 28 | template 29 | class VoidLiteral; 30 | template 31 | class NotExpression; 32 | template 33 | class EqualityExpression; 34 | template 35 | class InequalityExpression; 36 | template 37 | class GtExpression; 38 | template 39 | class GteExpression; 40 | template 41 | class LtExpression; 42 | template 43 | class LteExpression; 44 | template 45 | class ExpressionStatement; 46 | template 47 | class Block; 48 | template 49 | class FuncDecl; 50 | template 51 | class FuncCallExpression; 52 | template 53 | class ListLiteralExpression; 54 | template 55 | class DynamicAccessExpression; 56 | template 57 | class DynamicStoreExpression; 58 | template 59 | class StaticAccessExpression; 60 | template 61 | class StaticStoreExpression; 62 | template 63 | class VarDecl; 64 | template 65 | class IfStatement; 66 | template 67 | class ForCondition; 68 | template 69 | class ReturnStatement; 70 | 71 | template 72 | class Visitor { 73 | 74 | public: 75 | virtual void visitAdditionExpression(AdditionExpression& expr)=0; 76 | virtual void visitAssignmentExpression(AssignmentExpression& expr)=0; 77 | virtual void visitSubtractionExpression(SubtractionExpression& expr)=0; 78 | virtual void visitMultiplicationExpression(MultiplicationExpression& expr)=0; 79 | virtual void visitDivisionExpression(DivisionExpression& expr)=0; 80 | virtual void visitIntegerExpression(IntegerExpression& expr)=0; 81 | virtual void visitDoubleExpression(DoubleExpression& expr)=0; 82 | virtual void visitStringExpression(StringExpression& expr)=0; 83 | virtual void visitVariableExpression(VariableExpression& expr)=0; 84 | virtual void visitBoolLiteral(BoolLiteral& expr)=0; 85 | virtual void visitVoidLiteral(VoidLiteral& expr)=0; 86 | virtual void visitNotExpression(NotExpression& expr)=0; 87 | virtual void visitEqualityExpression(EqualityExpression& expr)=0; 88 | virtual void visitInequalityExpression(InequalityExpression& expr)=0; 89 | virtual void visitGtExpression(GtExpression& expr)=0; 90 | virtual void visitGteExpression(GteExpression& expr)=0; 91 | virtual void visitLtExpression(LtExpression& expr)=0; 92 | virtual void visitLteExpression(LteExpression& expr)=0; 93 | virtual void visitFuncCallExpression(FuncCallExpression& expr)=0; 94 | virtual void visitListLiteralExpression(ListLiteralExpression& expr)=0; 95 | virtual void visitDynamicAccessExpression(DynamicAccessExpression& expr)=0; 96 | virtual void visitDynamicStoreExpression(DynamicStoreExpression& expr)=0; 97 | virtual void visitStaticAccessExpression(StaticAccessExpression& expr)=0; 98 | virtual void visitStaticStoreExpression(StaticStoreExpression& expr)=0; 99 | virtual void visitExpressionStatement(ExpressionStatement& stmt)=0; 100 | virtual void visitIfStatement(IfStatement& stmt)=0; 101 | virtual void visitForCondition(ForCondition& stmt)=0; 102 | virtual void visitReturnStatement(ReturnStatement& stmt)=0; 103 | virtual void visitBlock(Block& block)=0; 104 | virtual void visitFuncDecl(FuncDecl& funcDecl)=0; 105 | virtual void visitVarDecl(VarDecl& varDecl)=0; 106 | 107 | }; 108 | 109 | }} 110 | 111 | #endif 112 | -------------------------------------------------------------------------------- /ast/void_literal.h: -------------------------------------------------------------------------------- 1 | #ifndef VAIVEN_AST_HEADER_VOID_LITERAL 2 | #define VAIVEN_AST_HEADER_VOID_LITERAL 3 | 4 | #include 5 | #include "expression.h" 6 | 7 | using std::unique_ptr; 8 | 9 | namespace vaiven { namespace ast { 10 | 11 | template 12 | class VoidLiteral : public Expression { 13 | 14 | public: 15 | VoidLiteral() {} 16 | 17 | void accept(Visitor& v) { 18 | return v.visitVoidLiteral(*this); 19 | } 20 | virtual ~VoidLiteral() {}; 21 | }; 22 | 23 | }} 24 | 25 | #endif 26 | -------------------------------------------------------------------------------- /bench/bench.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | echo > bench_log 4 | 5 | export TIMEFORMAT="%U" 6 | 7 | BASELINE=0 8 | COMPARISON=0 9 | 10 | run_vvn_bench() { 11 | run_cmd_bench $1 "./$1.vvn.sh | ../vvn" 12 | } 13 | 14 | run_cmd_bench() { 15 | echo -n "[$1] " 16 | TIME=$( time ( 17 | (eval "$2") 2>&1 > bench_log_$1 18 | ) 2>&1) 19 | DIFFERENCE="$( echo $TIME - $BASELINE | bc -l )" 20 | echo "$DIFFERENCE over/under baseline of $BASELINE ($TIME)" 21 | eval "TIME_$1=$TIME" 22 | eval "DIFFERENCE_$1=$DIFFERENCE" 23 | } 24 | 25 | compare() { 26 | AVARNAME="TIME_$1" 27 | BVARNAME="TIME_$2" 28 | A="${!AVARNAME}" 29 | B="${!BVARNAME}" 30 | CHANGEX=$(printf %.2f $(echo "$B / $A" | bc -l)) 31 | echo ":: $1 ${CHANGEX}X faster than $2 ($B / $A)" 32 | } 33 | 34 | compare_adjust_baseline() { 35 | AVARNAME="DIFFERENCE_$1" 36 | BVARNAME="DIFFERENCE_$2" 37 | A="${!AVARNAME}" 38 | B="${!BVARNAME}" 39 | CHANGEX=$(printf %.2f $(echo "$B / $A" | bc -l)) 40 | echo ":: $1 ${CHANGEX}X faster than $2 ($B / $A)" 41 | } 42 | 43 | baseline() { 44 | BASELINEVARNAME="TIME_$1" 45 | BASELINE="${!BASELINEVARNAME}" 46 | } 47 | 48 | echo 49 | echo V8/dart comparison 50 | echo 51 | 52 | run_cmd_bench fibvvn "./fib_45.vvn.sh | ../vvn" 53 | run_cmd_bench fibjs "js fib_45.js" 54 | run_cmd_bench fibdart "dart fib_45.dart" 55 | compare fibvvn fibdart 56 | compare fibvvn fibjs 57 | 58 | run_cmd_bench lcfvvn "cat lowest_common_factor.vvn | ../vvn" 59 | run_cmd_bench lcfjs "js lowest_common_factor.js" 60 | compare lcfvvn lcfjs 61 | 62 | echo 63 | echo interp/cc/hot comparison 64 | echo 65 | 66 | run_vvn_bench loop_empty_interp 67 | run_vvn_bench loop_empty_cc 68 | run_vvn_bench loop_empty_hot 69 | 70 | baseline loop_empty_interp 71 | run_vvn_bench loop_with_ops_interp 72 | run_vvn_bench loop_with_function_interp 73 | compare_adjust_baseline loop_with_function_interp loop_with_ops_interp 74 | 75 | baseline loop_empty_cc 76 | run_vvn_bench loop_with_ops_cc 77 | compare loop_with_ops_cc loop_with_ops_interp 78 | run_vvn_bench loop_with_function_cc 79 | compare_adjust_baseline loop_with_function_cc loop_with_ops_cc 80 | 81 | baseline loop_empty_hot 82 | run_vvn_bench loop_with_ops_hot 83 | compare loop_with_ops_hot loop_with_ops_interp 84 | run_vvn_bench loop_with_function_hot 85 | compare loop_with_function_hot loop_with_ops_hot 86 | compare loop_with_function_hot loop_with_ops_interp 87 | 88 | echo 89 | echo recursion comparison 90 | echo 91 | 92 | BASELINE=0 93 | run_vvn_bench recurse_with_ops 94 | compare recurse_with_ops loop_with_ops_interp 95 | compare recurse_with_ops loop_with_ops_cc 96 | compare recurse_with_ops loop_with_ops_hot 97 | 98 | echo 99 | echo garbage comparison 100 | echo 101 | 102 | baseline loop_empty_cc 103 | run_vvn_bench loop_with_garbagemem_cc 104 | compare loop_with_garbagemem_cc loop_empty_cc 105 | BASELINE=0 106 | run_cmd_bench loop_empty_js "js loop_empty.js" 107 | baseline loop_empty_js 108 | run_cmd_bench loop_with_garbagemem_js "js loop_with_garbagemem.js" 109 | compare loop_with_garbagemem_js loop_with_garbagemem_cc 110 | 111 | echo 112 | echo compilation comparison 113 | echo 114 | 115 | BASELINE=0 116 | run_vvn_bench repeat_functions 117 | compare loop_with_ops_interp repeat_functions 118 | -------------------------------------------------------------------------------- /bench/fib_45.dart: -------------------------------------------------------------------------------- 1 | int fib(int x) { 2 | if (x == 0) { 3 | return 0; 4 | } else if (x == 1) { 5 | return 1; 6 | } else { 7 | return fib(x - 1) + fib(x - 2); 8 | } 9 | } 10 | 11 | main() { 12 | print(fib(45)); 13 | } 14 | -------------------------------------------------------------------------------- /bench/fib_45.js: -------------------------------------------------------------------------------- 1 | function fib(x) { 2 | if (x == 0) { 3 | return 0; 4 | } else if (x == 1) { 5 | return 1; 6 | } else { 7 | return fib(x - 1) + fib(x - 2); 8 | } 9 | } 10 | 11 | console.log(fib(45)); 12 | -------------------------------------------------------------------------------- /bench/fib_45.vvn.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | cat < 0 12 | loop(50000000) 13 | primings = primings - 1 14 | end 15 | 16 | loop(1) 17 | 18 | EOF 19 | -------------------------------------------------------------------------------- /bench/loop_empty_interp.vvn.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | cat < 0 17 | loop(50000000) 18 | primings = primings - 1 19 | end 20 | 21 | loop(1) 22 | 23 | EOF 24 | -------------------------------------------------------------------------------- /bench/loop_with_function_interp.vvn.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | cat < 0 13 | loop(50000000) 14 | primings = primings - 1 15 | end 16 | 17 | loop(1) 18 | 19 | EOF 20 | -------------------------------------------------------------------------------- /bench/loop_with_ops_interp.vvn.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | cat < lim) { 3 | return true; 4 | } else if (val % div != 0) { // is not evenly divisible 5 | return false; 6 | } 7 | 8 | return isEvenlyDivisible(val, div + 1, lim); 9 | } 10 | 11 | function test(lim) { 12 | var val = 10; 13 | while (!isEvenlyDivisible(val, 2, lim)) { 14 | val += 2; 15 | } 16 | 17 | return val; 18 | } 19 | 20 | console.log(test(1)); 21 | console.log(test(5)); 22 | console.log(test(10)); 23 | console.log(test(15)); 24 | console.log(test(20)); 25 | -------------------------------------------------------------------------------- /bench/lowest_common_factor.vvn: -------------------------------------------------------------------------------- 1 | fn isEvenlyDivisible of val, div, lim is 2 | if div > lim 3 | ret true 4 | else if floor(val / div) * div != val // is not evenly divisible 5 | ret false 6 | end 7 | 8 | isEvenlyDivisible(val, div + 1, lim) 9 | end 10 | 11 | fn test of lim is 12 | var val = 10 13 | for !isEvenlyDivisible(val, 2, lim) 14 | val += 2 15 | end 16 | 17 | val 18 | end 19 | 20 | test(1) 21 | test(5) 22 | test(10) 23 | test(15) 24 | test(20) 25 | -------------------------------------------------------------------------------- /bench/recurse_with_ops.vvn.sh: -------------------------------------------------------------------------------- 1 | cat <()); 40 | } 41 | 42 | if (hasDoubleConvertableTypeError) { 43 | cc.bind(doubleConvertableTypeErrorLabel); 44 | cc.call((size_t) &expectedIntOrDouble, FuncSignature0()); 45 | } 46 | 47 | if (hasBoolTypeError) { 48 | cc.bind(boolTypeErrorLabel); 49 | cc.call((size_t) &expectedBool, FuncSignature0()); 50 | } 51 | 52 | if (hasStringTypeError) { 53 | cc.bind(stringTypeErrorLabel); 54 | cc.call((size_t) &expectedStr, FuncSignature0()); 55 | } 56 | 57 | if (hasNoFuncError) { 58 | cc.bind(noFuncErrorLabel); 59 | cc.call((size_t) &noSuchFunction, FuncSignature0()); 60 | } 61 | 62 | if (hasNoVarError) { 63 | cc.bind(noVarErrorLabel); 64 | cc.call((size_t) &noSuchVar, FuncSignature0()); 65 | } 66 | 67 | if (hasDupVarError) { 68 | cc.bind(dupVarErrorLabel); 69 | cc.call((size_t) &duplicateVar, FuncSignature0()); 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /error_compiler.h: -------------------------------------------------------------------------------- 1 | #ifndef VAIVEN_VISITOR_HEADER_ERROR_COMPILER 2 | #define VAIVEN_VISITOR_HEADER_ERROR_COMPILER 3 | 4 | #include "type_info.h" 5 | #include "value.h" 6 | #include "asmjit/src/asmjit/asmjit.h" 7 | 8 | namespace vaiven { 9 | 10 | using asmjit::X86Compiler; 11 | 12 | class ErrorCompiler { 13 | 14 | public: 15 | ErrorCompiler(X86Compiler& cc) : cc(cc), 16 | hasIntTypeError(false), hasBoolTypeError(false), hasStringTypeError(false), 17 | hasNoFuncError(false), hasNoVarError(false), hasDupVarError(false), 18 | intTypeErrorLabel(cc.newLabel()), boolTypeErrorLabel(cc.newLabel()), 19 | stringTypeErrorLabel(cc.newLabel()), noFuncErrorLabel(cc.newLabel()), 20 | noVarErrorLabel(cc.newLabel()), dupVarErrorLabel(cc.newLabel()), 21 | hasDoubleConvertableTypeError(false), 22 | doubleConvertableTypeErrorLabel(cc.newLabel()) {} 23 | 24 | void generateTypeErrorEpilog(); 25 | X86Compiler& cc; 26 | 27 | void intTypeError(); 28 | void boolTypeError(); 29 | void stringTypeError(); 30 | void noFuncError(); 31 | void noVarError(); 32 | void dupVarError(); 33 | 34 | asmjit::Label intTypeErrorLabel; 35 | bool hasIntTypeError; 36 | 37 | asmjit::Label doubleConvertableTypeErrorLabel; 38 | bool hasDoubleConvertableTypeError; 39 | 40 | asmjit::Label boolTypeErrorLabel; 41 | bool hasBoolTypeError; 42 | 43 | asmjit::Label stringTypeErrorLabel; 44 | bool hasStringTypeError; 45 | 46 | asmjit::Label noFuncErrorLabel; 47 | bool hasNoFuncError; 48 | 49 | asmjit::Label noVarErrorLabel; 50 | bool hasNoVarError; 51 | 52 | asmjit::Label dupVarErrorLabel; 53 | bool hasDupVarError; 54 | 55 | }; 56 | 57 | } 58 | 59 | #endif 60 | -------------------------------------------------------------------------------- /firstcompile.h: -------------------------------------------------------------------------------- 1 | #ifndef VAIVEN_HEADER_FIRST_COMPILE 2 | #define VAIVEN_HEADER_FIRST_COMPILE 3 | 4 | #include "functions.h" 5 | #include "type_info.h" 6 | #include "error_compiler.h" 7 | #include "ast/funcdecl.h" 8 | #include "asmjit/src/asmjit/asmjit.h" 9 | 10 | namespace vaiven { 11 | 12 | void firstCompile(vaiven::Functions& funcs, ast::FuncDecl<>& funcDecl); 13 | 14 | void firstOptimizations(ast::FuncDecl<>& decl, Functions& funcs, FunctionUsage& usageInfo, asmjit::X86Compiler& cc, vector& argRegs, ErrorCompiler& error, asmjit::Label funcLabel); 15 | void generateOptimizeEpilog(ast::FuncDecl<>& decl, asmjit::FuncSignature& sig, asmjit::X86Compiler& cc, asmjit::Label& optimizeLabel, vector& argRegs, Functions& funcs); 16 | void generateTypeShapeProlog(ast::FuncDecl<>& decl, FunctionUsage* usage, asmjit::X86Compiler& cc, asmjit::Label* optimizeLabel, vector& argRegs); 17 | 18 | } 19 | 20 | #endif 21 | -------------------------------------------------------------------------------- /function_usage.h: -------------------------------------------------------------------------------- 1 | #ifndef VAIVEN_HEADER_FUNCTION_USAGE 2 | #define VAIVEN_HEADER_FUNCTION_USAGE 3 | 4 | #include "inttypes.h" 5 | 6 | #include "value.h" 7 | #include "type_info.h" 8 | 9 | namespace vaiven { 10 | 11 | const short INT_SHAPE = INT_TAG >> 48; 12 | const short BOOL_SHAPE = BOOL_TAG >> 48; 13 | const short VOID_SHAPE = VOID >> 48; 14 | const short DOUBLE_SHAPE = 0x08; 15 | const short LIST_SHAPE = 0x10; 16 | const short STRING_SHAPE = 0x20; 17 | const short OBJECT_SHAPE = 0x40; 18 | const short PRIMITIVE_TAG_SHIFT = 48; 19 | const short POINTER_TAG_SHIFT = 4; 20 | 21 | const int HOT_COUNT = 10; 22 | 23 | class ArgumentShape { 24 | public: 25 | short raw; 26 | 27 | inline bool isPure() { 28 | // is power of two trick 29 | return raw && !(raw & (raw - 1)); 30 | } 31 | 32 | inline bool isPureInt() { 33 | return (raw & ~INT_SHAPE) == 0; 34 | } 35 | 36 | inline bool isPureBool() { 37 | return (raw & ~BOOL_SHAPE) == 0; 38 | } 39 | 40 | inline bool isPureVoid() { 41 | return (raw & ~VOID_SHAPE) == 0; 42 | } 43 | 44 | inline bool isPureDouble() { 45 | return (raw & ~DOUBLE_SHAPE) == 0; 46 | } 47 | 48 | inline bool isPureObject() { 49 | return (raw & ~OBJECT_SHAPE) == 0; 50 | } 51 | 52 | inline bool isPureList() { 53 | return (raw & ~LIST_SHAPE) == 0; 54 | } 55 | 56 | inline bool isPureString() { 57 | return (raw & ~STRING_SHAPE) == 0; 58 | } 59 | 60 | inline VaivenStaticType getStaticType() { 61 | if (!isPure()) { 62 | return VAIVEN_STATIC_TYPE_UNKNOWN; 63 | } else if (isPureInt()) { 64 | return VAIVEN_STATIC_TYPE_INT; 65 | } else if (isPureVoid()) { 66 | return VAIVEN_STATIC_TYPE_VOID; 67 | } else if (isPureDouble()) { 68 | return VAIVEN_STATIC_TYPE_DOUBLE; 69 | } else if (isPureObject()) { 70 | return VAIVEN_STATIC_TYPE_OBJECT; 71 | } else if (isPureList()) { 72 | return VAIVEN_STATIC_TYPE_LIST; 73 | } else if (isPureString()) { 74 | return VAIVEN_STATIC_TYPE_STRING; 75 | } 76 | 77 | return VAIVEN_STATIC_TYPE_UNKNOWN; 78 | } 79 | 80 | }; 81 | 82 | class FunctionUsage { 83 | public: 84 | int32_t count; 85 | // variably sized -- allocate with new (alloca(...)) FunctionUsage 86 | ArgumentShape argShapes[0]; 87 | }; 88 | 89 | } 90 | 91 | #endif 92 | -------------------------------------------------------------------------------- /functions.h: -------------------------------------------------------------------------------- 1 | #ifndef VAIVEN_HEADER_FUNCTIONS 2 | #define VAIVEN_HEADER_FUNCTIONS 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #include "asmjit/src/asmjit/asmjit.h" 9 | 10 | #include "value.h" 11 | #include "function_usage.h" 12 | #include "type_info.h" 13 | #include "ast/funcdecl.h" 14 | 15 | using std::map; 16 | using std::string; 17 | using std::unique_ptr; 18 | 19 | namespace vaiven { 20 | 21 | typedef Value (*OverkillFunc)(Value rdi, Value rsi, Value rdx, Value rcx, Value r8, Value r9, Value stack1, Value stack2); 22 | 23 | class Function { 24 | public: 25 | Function(const Function& that) = delete; 26 | Function(asmjit::JitRuntime* runtime, 27 | int argc, 28 | unique_ptr usage, 29 | ast::FuncDecl<>* ast) 30 | : runtime(runtime), argc(argc), usage(std::move(usage)), ast(ast), isPure(false), isNative(false) {}; 31 | 32 | ~Function() { 33 | if (!isNative) { 34 | runtime->release(fptr); 35 | } 36 | } 37 | 38 | bool isNative; 39 | int argc; 40 | int worstSize; 41 | bool isPure; // for native functions 42 | OverkillFunc fptr; 43 | OverkillFunc slowfptr; 44 | unique_ptr usage; 45 | unique_ptr > ast; 46 | 47 | private: 48 | asmjit::JitRuntime* runtime; 49 | }; 50 | 51 | class DuplicateFunctionError { 52 | public: 53 | DuplicateFunctionError(string name) : name(name) {}; 54 | string name; 55 | }; 56 | 57 | class Functions { 58 | public: 59 | asmjit::JitRuntime runtime; 60 | 61 | void addNative(string name, int argc, void* fptr, bool isPure) { 62 | funcs[name] = unique_ptr(new Function(NULL, argc, unique_ptr(), NULL)); 63 | funcs[name]->isNative = true; 64 | funcs[name]->fptr = (OverkillFunc) fptr; 65 | funcs[name]->isPure = isPure; 66 | } 67 | 68 | void prepareFunc(string name, int argc, unique_ptr usage, 69 | ast::FuncDecl<>* ast) { 70 | if (funcs.find(name) != funcs.end()) { 71 | throw DuplicateFunctionError(name); 72 | } 73 | funcs[name] = unique_ptr(new Function(&runtime, argc, std::move(usage), ast)); 74 | } 75 | 76 | void finalizeFunc(string name, asmjit::CodeHolder* holder) { 77 | int worstSize = holder->getCodeSize(); 78 | runtime.add(&funcs[name]->fptr, holder); 79 | funcs[name]->worstSize = worstSize; 80 | } 81 | 82 | // private: 83 | map > funcs; 84 | }; 85 | 86 | } 87 | 88 | #endif 89 | -------------------------------------------------------------------------------- /heap.cpp: -------------------------------------------------------------------------------- 1 | #include "heap.h" 2 | 3 | #include 4 | #include 5 | 6 | #include "stack.h" 7 | 8 | using namespace vaiven; 9 | using std::min; 10 | using std::max; 11 | 12 | // set by interpreter 13 | Heap* vaiven::globalHeap = NULL; 14 | 15 | GcableType vaiven::Gcable::getType() { 16 | return (GcableType) (((GcableType) this->type) & ~GcableMarkBit); 17 | } 18 | 19 | bool vaiven::Gcable::isMarked() { 20 | return (this->type & GcableMarkBit) == GcableMarkBit; 21 | } 22 | 23 | bool vaiven::Gcable::mark() { 24 | if (isMarked()) { 25 | return false; 26 | } 27 | 28 | this->type = (GcableType) (((GcableType) this->type) | GcableMarkBit); 29 | return true; 30 | } 31 | 32 | void vaiven::Gcable::unmark() { 33 | this->type = (GcableType) (((GcableType) this->type) & ~GcableMarkBit); 34 | } 35 | 36 | 37 | GcableList* vaiven::Heap::newList() { 38 | if (isFull()) { 39 | gc(); 40 | } 41 | 42 | GcableList* ptr = new GcableList(); 43 | owned_ptrs.insert(ptr); 44 | heap_min = min(heap_min, (uint64_t) ptr); 45 | heap_max = max(heap_max, (uint64_t) ptr); 46 | return ptr; 47 | } 48 | 49 | GcableString* vaiven::Heap::newString() { 50 | if (isFull()) { 51 | gc(); 52 | } 53 | 54 | GcableString* ptr = new GcableString(); 55 | owned_ptrs.insert(ptr); 56 | heap_min = min(heap_min, (uint64_t) ptr); 57 | heap_max = max(heap_max, (uint64_t) ptr); 58 | return ptr; 59 | } 60 | 61 | GcableObject* vaiven::Heap::newObject() { 62 | if (isFull()) { 63 | gc(); 64 | } 65 | 66 | GcableObject* ptr = new GcableObject(); 67 | owned_ptrs.insert(ptr); 68 | heap_min = min(heap_min, (uint64_t) ptr); 69 | heap_max = max(heap_max, (uint64_t) ptr); 70 | return ptr; 71 | } 72 | 73 | bool vaiven::Heap::owns(void* ptr) { 74 | uint64_t addr = (uint64_t) ptr; 75 | // inside heap and is aligned to 64 bits 76 | if (addr < heap_min || addr > heap_max || addr & 7 != 1) { 77 | return false; 78 | } 79 | 80 | return owned_ptrs.find((Gcable*) ptr) != owned_ptrs.end(); 81 | } 82 | 83 | bool vaiven::Heap::isFull() { 84 | return owned_ptrs.size() >= size; 85 | } 86 | 87 | void vaiven::Heap::mark(Gcable* ptr) { 88 | if (!owns(ptr)) { 89 | return; 90 | } 91 | 92 | if (ptr->mark()) { 93 | return; 94 | } 95 | 96 | switch (ptr->getType()) { 97 | case GCABLE_TYPE_LIST: 98 | { 99 | GcableList* list = (GcableList*) ptr; 100 | for (vector::iterator it = list->list.begin(); it != list->list.end(); ++it) { 101 | mark(it->getPtr()); 102 | } 103 | break; 104 | } 105 | case GCABLE_TYPE_STRING: 106 | // already marked, nothing to do 107 | break; 108 | case GCABLE_TYPE_OBJECT: 109 | { 110 | GcableObject* object = (GcableObject*) ptr; 111 | for (unordered_map::iterator it = object->properties.begin(); it != object->properties.end(); ++it) { 112 | mark(it->second.getPtr()); 113 | } 114 | } 115 | } 116 | } 117 | 118 | void vaiven::Heap::sweep() { 119 | unordered_set::iterator it = owned_ptrs.begin(); 120 | while (it != owned_ptrs.end()) { 121 | Gcable* gcable = (Gcable*) *it; 122 | if (!gcable->isMarked()) { 123 | switch (gcable->getType()) { 124 | case GCABLE_TYPE_LIST: 125 | delete static_cast(gcable); break; 126 | case GCABLE_TYPE_STRING: 127 | delete static_cast(gcable); break; 128 | case GCABLE_TYPE_OBJECT: 129 | delete static_cast(gcable); break; 130 | } 131 | it = owned_ptrs.erase(it); 132 | } else { 133 | gcable->unmark(); 134 | ++it; 135 | } 136 | } 137 | } 138 | 139 | void vaiven::Heap::free(Gcable* ptr) { 140 | if (ptr->getType() == GCABLE_TYPE_LIST) { 141 | delete (GcableList*) ptr; 142 | } else if (ptr->getType() == GCABLE_TYPE_STRING) { 143 | delete (GcableString*) ptr; 144 | } else if (ptr->getType() == GCABLE_TYPE_OBJECT) { 145 | delete (GcableObject*) ptr; 146 | } 147 | owned_ptrs.erase(ptr); 148 | } 149 | 150 | void vaiven::Heap::gc() { 151 | Stack callStack; 152 | StackFrame frame = callStack.top(); 153 | while (true) { 154 | for (int i = 0; i < frame.size; ++i) { 155 | mark((Gcable*) frame.locals[i]); 156 | } 157 | 158 | if (!frame.hasNext()) { 159 | break; 160 | } 161 | 162 | frame = frame.next(); 163 | } 164 | 165 | for (std::deque::iterator it = interpreterStack.c.begin(); 166 | it != interpreterStack.c.end(); 167 | ++it) { 168 | mark((Gcable*) it->getPtr()); 169 | 170 | } 171 | 172 | std::map scopeMap; 173 | globalScope.fill(scopeMap); 174 | 175 | for (std::map::iterator it = scopeMap.begin(); 176 | it != scopeMap.end(); 177 | ++it) { 178 | mark((Gcable*) it->second.getPtr()); 179 | } 180 | 181 | sweep(); 182 | 183 | size = max((int) owned_ptrs.size() * HEAP_FACTOR, MIN_HEAP_SIZE); 184 | } 185 | -------------------------------------------------------------------------------- /heap.h: -------------------------------------------------------------------------------- 1 | #ifndef VAIVEN_VISITOR_HEADER_HEAP 2 | #define VAIVEN_VISITOR_HEADER_HEAP 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include "scope.h" 10 | #include "value.h" 11 | #include "util.h" 12 | 13 | using std::unordered_map; 14 | using std::unordered_set; 15 | using std::string; 16 | using std::vector; 17 | 18 | namespace vaiven { 19 | 20 | // make these bits so they can be stored in shapes bitmaps 21 | enum GcableType { 22 | GCABLE_TYPE_LIST = 1, 23 | GCABLE_TYPE_STRING = 2, 24 | GCABLE_TYPE_OBJECT = 4, 25 | 26 | Internal_ForceMyEnumIntSize = 1 << 30 27 | }; 28 | 29 | const int GcableMarkBit = 8; 30 | const int HEAP_FACTOR = 2; 31 | const int MIN_HEAP_SIZE = 65536; 32 | 33 | struct Gcable { 34 | public: 35 | Gcable(GcableType type) : type(type) {}; 36 | GcableType getType(); 37 | bool isMarked(); 38 | bool mark(); 39 | void unmark(); 40 | 41 | private: 42 | GcableType type; 43 | }; 44 | 45 | struct GcableList : public Gcable { 46 | public: 47 | GcableList() : Gcable(GCABLE_TYPE_LIST) {}; 48 | 49 | vector list; 50 | }; 51 | 52 | struct GcableString : public Gcable { 53 | public: 54 | GcableString() : Gcable(GCABLE_TYPE_STRING) {}; 55 | GcableString(string str) : Gcable(GCABLE_TYPE_STRING), str(str) {}; 56 | 57 | string str; 58 | }; 59 | 60 | struct GcableObject : public Gcable { 61 | public: 62 | GcableObject() : Gcable(GCABLE_TYPE_OBJECT) {}; 63 | 64 | unordered_map properties; 65 | }; 66 | 67 | class Heap { 68 | public: 69 | Heap(stack_with_container& interpreterStack, Scope& globalScope) 70 | : size(MIN_HEAP_SIZE), heap_min(0xFFFFFFFFFFFFFFFF), heap_max(0), 71 | interpreterStack(interpreterStack), globalScope(globalScope) {}; 72 | int size; 73 | uint64_t heap_min; 74 | uint64_t heap_max; 75 | 76 | // for roots 77 | Scope& globalScope; 78 | stack_with_container& interpreterStack; 79 | 80 | GcableList* newList(); 81 | GcableString* newString(); 82 | GcableObject* newObject(); 83 | void free(Gcable* ptr); 84 | bool isFull(); 85 | bool owns(void* ptr); 86 | void mark(Gcable* ptr); 87 | void sweep(); 88 | void gc(); 89 | 90 | // TODO this is TERRIBLE 91 | unordered_set owned_ptrs; 92 | }; 93 | 94 | extern Heap* globalHeap; 95 | 96 | } 97 | 98 | #endif 99 | -------------------------------------------------------------------------------- /main.cpp: -------------------------------------------------------------------------------- 1 | #include "stdio.h" 2 | #include "parser.h" 3 | #include "functions.h" 4 | #include "type_info.h" 5 | #include "runtime_error.h" 6 | #include "std.h" 7 | #include "firstcompile.h" 8 | #include "visitor/print_visitor.h" 9 | #include "visitor/interpreter.h" 10 | 11 | #include 12 | 13 | #include "asmjit/src/asmjit/asmjit.h" 14 | 15 | using std::cin; 16 | using std::cout; 17 | using std::endl; 18 | 19 | using namespace vaiven; 20 | using namespace asmjit; 21 | 22 | void printTokenStream(Tokenizer& tokenizer); 23 | void printExpressionStream(Parser& tokenizer); 24 | 25 | int main() { 26 | Tokenizer tokenizer(cin); 27 | Parser parser(tokenizer); 28 | 29 | //printTokenStream(tokenizer); 30 | printExpressionStream(parser); 31 | } 32 | 33 | 34 | // Error handler that just prints the error and lets AsmJit ignore it. 35 | class PrintErrorHandler : public asmjit::ErrorHandler { 36 | public: 37 | // Return `true` to set last error to `err`, return `false` to do nothing. 38 | bool handleError(asmjit::Error err, const char* message, asmjit::CodeEmitter* origin) override { 39 | fprintf(stderr, "Error: %s\n", message); 40 | return false; 41 | } 42 | }; 43 | 44 | void printExpressionStream(Parser& parser) { 45 | Functions funcs; 46 | init_std(funcs); 47 | unique_ptr > cur = parser.parseLogicalGroup(); 48 | visitor::Interpreter interpreter(funcs); 49 | 50 | while (cur.get() != NULL || parser.errors.size() > 0) { 51 | if (parser.errors.size() > 0) { 52 | for (vector::iterator it = parser.errors.begin(); it != parser.errors.end(); ++it) { 53 | cout << "Parse Error: " << it->error << " at " << it->location << endl; 54 | } 55 | parser.errors.clear(); 56 | 57 | if (cur.get() == NULL) { 58 | cur = parser.parseLogicalGroup(); 59 | continue; 60 | } 61 | } 62 | 63 | if (!parser.lastLogicalGroupWasEvaluatable) { 64 | try { 65 | firstCompile(funcs, static_cast&>(*cur)); 66 | cur.release(); // Functions owns pointer now 67 | } catch (DuplicateFunctionError e) { 68 | cout << "function " << e.name << " already defined" << endl; 69 | } 70 | cur = parser.parseLogicalGroup(); 71 | continue; 72 | } 73 | 74 | 75 | int error = setjmp(errorJmpBuf); 76 | if (error) { 77 | defaultHandle((vaiven::ErrorCode) error); 78 | cur = parser.parseLogicalGroup(); 79 | continue; 80 | } 81 | 82 | Value result; 83 | try { 84 | result = interpreter.interpret(*cur); 85 | } catch(Value v) { 86 | result = v; 87 | } 88 | print(result); 89 | 90 | cur = parser.parseLogicalGroup(); 91 | } 92 | } 93 | 94 | void printTokenStream(Tokenizer& tokenizer) { 95 | unique_ptr cur; 96 | do { 97 | cur = tokenizer.next(); 98 | switch(cur->type) { 99 | case TOKEN_TYPE_PLUS: 100 | cout << "+" << endl; break; 101 | case TOKEN_TYPE_MINUS: 102 | cout << "-" << endl; break; 103 | case TOKEN_TYPE_OPEN_BRACE: 104 | cout << "{" << endl; break; 105 | case TOKEN_TYPE_CLOSE_BRACE: 106 | cout << "}" << endl; break; 107 | case TOKEN_TYPE_OPEN_PAREN: 108 | cout << "(" << endl; break; 109 | case TOKEN_TYPE_CLOSE_PAREN: 110 | cout << ")" << endl; break; 111 | case TOKEN_TYPE_MULTIPLY: 112 | cout << "*" << endl; break; 113 | case TOKEN_TYPE_DIVIDE: 114 | cout << "/" << endl; break; 115 | case TOKEN_TYPE_EQ: 116 | cout << "=" << endl; break; 117 | case TOKEN_TYPE_EQEQ: 118 | cout << "==" << endl; break; 119 | case TOKEN_TYPE_GT: 120 | cout << ">" << endl; break; 121 | case TOKEN_TYPE_COMMA: 122 | cout << "," << endl; break; 123 | case TOKEN_TYPE_SEMICOLON: 124 | cout << ";" << endl; break; 125 | case TOKEN_TYPE_FN: 126 | cout << "fn" << endl; break; 127 | case TOKEN_TYPE_END: 128 | cout << "end" << endl; break; 129 | case TOKEN_TYPE_ELSE: 130 | cout << "else" << endl; break; 131 | case TOKEN_TYPE_VAR: 132 | cout << "var" << endl; break; 133 | case TOKEN_TYPE_IS: 134 | cout << "is" << endl; break; 135 | case TOKEN_TYPE_IF: 136 | cout << "if" << endl; break; 137 | case TOKEN_TYPE_OF: 138 | cout << "of" << endl; break; 139 | case TOKEN_TYPE_DO: 140 | cout << "do" << endl; break; 141 | case TOKEN_TYPE_RET: 142 | cout << "ret" << endl; break; 143 | case TOKEN_TYPE_TRUE: 144 | cout << "true" << endl; break; 145 | case TOKEN_TYPE_FALSE: 146 | cout << "false" << endl; break; 147 | case TOKEN_TYPE_INTEGER: 148 | { 149 | IntegerToken* inttok = static_cast(cur.get()); 150 | cout << "int" << inttok->value << endl; 151 | } 152 | break; 153 | case TOKEN_TYPE_ID: 154 | { 155 | StringToken* strtok = static_cast(cur.get()); 156 | cout << "id" << strtok->lexeme << endl; 157 | } 158 | break; 159 | case TOKEN_TYPE_ERROR: 160 | { 161 | StringToken* strtok = static_cast(cur.get()); 162 | cout << "Error: " << strtok->lexeme << endl; 163 | } 164 | break; 165 | case TOKEN_TYPE_EOF: 166 | cout << "eof" << endl; break; 167 | } 168 | } while(cur->type != TOKEN_TYPE_EOF); 169 | } 170 | -------------------------------------------------------------------------------- /makefile: -------------------------------------------------------------------------------- 1 | VISITOR_OBJECTS = \ 2 | visitor/print_visitor.o \ 3 | visitor/interpreter.o \ 4 | visitor/ssa_builder.o \ 5 | visitor/assignment_producer.o \ 6 | 7 | SSA_OBJECTS = \ 8 | ssa/ssa.o \ 9 | ssa/print_visitor.o \ 10 | ssa/emitter.o \ 11 | ssa/reg_alloc.o \ 12 | ssa/constant_propagation.o \ 13 | ssa/instruction_combiner.o \ 14 | ssa/unused_code.o \ 15 | ssa/type_analysis.o \ 16 | ssa/constant_inliner.o \ 17 | ssa/forward_visitor.o \ 18 | ssa/jmp_threader.o \ 19 | ssa/inliner.o \ 20 | ssa/function_merge.o \ 21 | ssa/dominator_builder.o \ 22 | ssa/loop_invariant.o \ 23 | ssa/common_subexpression.o \ 24 | 25 | ASMJIT_OBJECTS = \ 26 | asmjit/src/asmjit/base/arch.o \ 27 | asmjit/src/asmjit/base/logging.o \ 28 | asmjit/src/asmjit/base/assembler.o \ 29 | asmjit/src/asmjit/base/operand.o \ 30 | asmjit/src/asmjit/base/codebuilder.o \ 31 | asmjit/src/asmjit/base/osutils.o \ 32 | asmjit/src/asmjit/base/codecompiler.o \ 33 | asmjit/src/asmjit/base/regalloc.o \ 34 | asmjit/src/asmjit/base/codeemitter.o \ 35 | asmjit/src/asmjit/base/runtime.o \ 36 | asmjit/src/asmjit/base/codeholder.o \ 37 | asmjit/src/asmjit/base/string.o \ 38 | asmjit/src/asmjit/base/constpool.o \ 39 | asmjit/src/asmjit/base/utils.o \ 40 | asmjit/src/asmjit/base/cpuinfo.o \ 41 | asmjit/src/asmjit/base/vmem.o \ 42 | asmjit/src/asmjit/base/func.o \ 43 | asmjit/src/asmjit/base/zone.o \ 44 | asmjit/src/asmjit/base/globals.o \ 45 | asmjit/src/asmjit/base/inst.o \ 46 | asmjit/src/asmjit/x86/x86assembler.o \ 47 | asmjit/src/asmjit/x86/x86logging.o \ 48 | asmjit/src/asmjit/x86/x86builder.o \ 49 | asmjit/src/asmjit/x86/x86operand.o \ 50 | asmjit/src/asmjit/x86/x86compiler.o \ 51 | asmjit/src/asmjit/x86/x86operand_regs.o \ 52 | asmjit/src/asmjit/x86/x86inst.o \ 53 | asmjit/src/asmjit/x86/x86regalloc.o \ 54 | asmjit/src/asmjit/x86/x86internal.o \ 55 | asmjit/src/asmjit/x86/x86instimpl.o \ 56 | 57 | MAIN_OBJECTS = \ 58 | main.o \ 59 | tokenizer.o \ 60 | parser.o \ 61 | runtime_error.o \ 62 | optimize.o \ 63 | firstcompile.o \ 64 | error_compiler.o \ 65 | std.o \ 66 | heap.o \ 67 | stack.o \ 68 | value.o \ 69 | 70 | DEBUGCXXFLAGS := -O0 -g -DSSA_DIAGNOSTICS -DDISASSEMBLY_DIAGNOSTICS -DOPTIMIZATION_DIAGNOSTICS -DINLINING_DIAGNOSTICS -DFIRST_COMPILE_DIAGNOSTICS 71 | RELEASECXXFLAGS := -O3 -DNDEBUG 72 | PROFILECXXFLAGS := -O3 -g -DNDEBUG 73 | CXXFLAGS := -DASMJIT_EMBED -std=c++11 -fno-omit-frame-pointer ${PROFILECXXFLAGS} -fPIC 74 | 75 | vvn : ${MAIN_OBJECTS} ${VISITOR_OBJECTS} ${ASMJIT_OBJECTS} ${SSA_OBJECTS} 76 | g++ $^ -o vvn 77 | 78 | clean: 79 | rm visitor/*.o 80 | rm ssa/*.o 81 | rm *.o 82 | rm vvn 83 | 84 | cleanasmjit: 85 | rm asmjit/src/asmjit/base/*.o 86 | rm asmjit/src/asmjit/x86/*.o 87 | -------------------------------------------------------------------------------- /optimize.h: -------------------------------------------------------------------------------- 1 | #ifndef VAIVEN_HEADER_OPTIMIZE 2 | #define VAIVEN_HEADER_OPTIMIZE 3 | 4 | #include "functions.h" 5 | #include "type_info.h" 6 | #include "ast/funcdecl.h" 7 | 8 | namespace vaiven { 9 | 10 | OverkillFunc optimize(vaiven::Functions& funcs, ast::FuncDecl<>& funcDecl); 11 | 12 | void performOptimize(ast::FuncDecl<>& decl, Functions& funcs, FunctionUsage& usageInfo); 13 | 14 | } 15 | 16 | #endif 17 | -------------------------------------------------------------------------------- /parser.h: -------------------------------------------------------------------------------- 1 | #ifndef VAIVEN_HEADER_PARSER 2 | #define VAIVEN_HEADER_PARSER 3 | 4 | #include 5 | #include 6 | 7 | #include "tokenizer.h" 8 | #include "ast/all.h" 9 | 10 | using std::unique_ptr; 11 | using std::string; 12 | 13 | namespace vaiven { 14 | 15 | class ParseError; 16 | 17 | class Parser { 18 | public: 19 | Parser(Tokenizer& tokenizer) 20 | : tokenizer(tokenizer), current(tokenizer.next()), newlineReplacement(TOKEN_TYPE_SEMICOLON), 21 | errorLocation("top level"), ignoreNextNext(false) {} 22 | 23 | unique_ptr > parseLogicalGroup(); 24 | 25 | unique_ptr > parseFuncDecl(); 26 | unique_ptr > parseStatement(); 27 | unique_ptr > parseControlStatement(); 28 | unique_ptr > parseBlock(); 29 | unique_ptr > parseVarDecl(); 30 | unique_ptr > parseIfStatement(); 31 | unique_ptr > parseForCondition(); 32 | unique_ptr > parseReturnStatement(); 33 | unique_ptr > parseExpressionStatement(); 34 | unique_ptr > parseExpression(); 35 | unique_ptr > parseAssignmentExpression(); 36 | unique_ptr > parseEqualityExpression(); 37 | unique_ptr > parseComparisonExpression(); 38 | unique_ptr > parseAddSubExpression(); 39 | unique_ptr > parseDivMulExpression(); 40 | unique_ptr > parseAccess(); 41 | unique_ptr > parseValue(); 42 | 43 | // Store this on the parser rather than using a visitor 44 | // to keep interpreter workflow fast 45 | bool lastLogicalGroupWasEvaluatable; 46 | 47 | vector errors; 48 | 49 | private: 50 | bool ignoreNextNext; 51 | void next(); 52 | void nextNoEol(); 53 | void nextOr(TokenType newlineType); 54 | 55 | Tokenizer& tokenizer; 56 | unique_ptr current; 57 | TokenType newlineReplacement; 58 | 59 | string errorLocation; 60 | }; 61 | 62 | class ParseError { 63 | public: 64 | string error; 65 | string location; 66 | 67 | ParseError(string error, string location) : error(error), location(location) {} 68 | }; 69 | 70 | } 71 | 72 | #endif 73 | -------------------------------------------------------------------------------- /runtime_error.cpp: -------------------------------------------------------------------------------- 1 | #include "runtime_error.h" 2 | 3 | #include 4 | 5 | using namespace std; 6 | 7 | jmp_buf vaiven::errorJmpBuf; 8 | std::string vaiven::errMsg; 9 | 10 | void vaiven::expectedInt() { 11 | throwError(EXPECTED_INT); 12 | } 13 | 14 | void vaiven::expectedBool() { 15 | throwError(EXPECTED_BOOL); 16 | } 17 | 18 | void vaiven::expectedDouble() { 19 | throwError(EXPECTED_DOUBLE); 20 | } 21 | 22 | void vaiven::noSuchFunction() { 23 | throwError(NO_SUCH_FUNCTION); 24 | } 25 | 26 | void vaiven::duplicateVar() { 27 | throwError(DUPLICATE_VAR); 28 | } 29 | 30 | void vaiven::noSuchVar() { 31 | throwError(NO_SUCH_VAR); 32 | } 33 | 34 | void vaiven::expectedStr() { 35 | throwError(EXPECTED_STR); 36 | } 37 | 38 | void vaiven::expectedList() { 39 | throwError(EXPECTED_LIST); 40 | } 41 | 42 | void vaiven::expectedObj() { 43 | throwError(EXPECTED_OBJ); 44 | } 45 | 46 | void vaiven::expectedIntOrDouble() { 47 | throwError(EXPECTED_INT_OR_DOUBLE); 48 | } 49 | 50 | void vaiven::expectedStrOrInt() { 51 | throwError(EXPECTED_STR_OR_INT); 52 | } 53 | 54 | void vaiven::expectedStrOrIntOrDouble() { 55 | throwError(EXPECTED_STR_OR_INT_OR_DOUBLE); 56 | } 57 | 58 | void vaiven::expectedListOrStr() { 59 | throwError(EXPECTED_LIST_OR_STR); 60 | } 61 | 62 | void vaiven::expectedListOrObj() { 63 | throwError(EXPECTED_LIST_OR_OBJ); 64 | } 65 | 66 | void vaiven::errString(std::string msg) { 67 | vaiven::errMsg = msg; 68 | throwError(USER_STR); 69 | } 70 | 71 | void vaiven::throwError(ErrorCode code) { 72 | longjmp(errorJmpBuf, code); 73 | } 74 | 75 | void vaiven::defaultHandle(ErrorCode code) { 76 | cout << "Error: "; 77 | switch(code) { 78 | case EXPECTED_INT: 79 | cout << "Got a non-integer in an integer operation" << endl; 80 | break; 81 | 82 | case EXPECTED_BOOL: 83 | cout << "Got a non-boolean in a boolean operation" << endl; 84 | break; 85 | 86 | case EXPECTED_DOUBLE: 87 | cout << "Got a non-double in a double operation" << endl; 88 | break; 89 | 90 | case EXPECTED_STR: 91 | cout << "Got a non-string in a string operation" << endl; 92 | break; 93 | 94 | case EXPECTED_LIST: 95 | cout << "Got a non-list in a list operation" << endl; 96 | break; 97 | 98 | case EXPECTED_OBJ: 99 | cout << "Got a non-object in an object operation" << endl; 100 | break; 101 | 102 | case EXPECTED_INT_OR_DOUBLE: 103 | cout << "Got a wrong type in an operation for ints/doubles" << endl; 104 | break; 105 | 106 | case EXPECTED_STR_OR_INT: 107 | cout << "Got a wrong type in an operation for ints/strings" << endl; 108 | break; 109 | 110 | case EXPECTED_STR_OR_INT_OR_DOUBLE: 111 | cout << "Got a wrong type in an operation for ints/strings/doubles" << endl; 112 | break; 113 | 114 | case EXPECTED_LIST_OR_STR: 115 | cout << "Got a wrong type in an operation for lists/strings" << endl; 116 | break; 117 | 118 | case EXPECTED_LIST_OR_OBJ: 119 | cout << "Got a wrong type in an operation for objects/lists" << endl; 120 | break; 121 | 122 | case NO_SUCH_FUNCTION: 123 | cout << "Called a function that does not exist" << endl; 124 | break; 125 | 126 | case DUPLICATE_VAR: 127 | cout << "Duplicate variable" << endl; 128 | break; 129 | 130 | case NO_SUCH_VAR: 131 | cout << "Accessed a var that does not exist" << endl; 132 | break; 133 | 134 | case USER_STR: 135 | cout << vaiven::errMsg << endl; 136 | break; 137 | } 138 | } 139 | -------------------------------------------------------------------------------- /runtime_error.h: -------------------------------------------------------------------------------- 1 | #ifndef VAIVEN_VISITOR_HEADER_RUNTIME_ERROR 2 | #define VAIVEN_VISITOR_HEADER_RUNTIME_ERROR 3 | 4 | #include 5 | #include 6 | 7 | namespace vaiven { 8 | 9 | extern jmp_buf errorJmpBuf; 10 | extern std::string errMsg; 11 | 12 | enum ErrorCode { 13 | EXPECTED_INT = 1, 14 | EXPECTED_BOOL = 2, 15 | EXPECTED_DOUBLE = 3, 16 | EXPECTED_STR = 4, 17 | EXPECTED_LIST = 5, 18 | EXPECTED_OBJ = 6, 19 | EXPECTED_INT_OR_DOUBLE = 7, 20 | EXPECTED_STR_OR_INT = 8, 21 | EXPECTED_STR_OR_INT_OR_DOUBLE = 9, 22 | EXPECTED_LIST_OR_STR = 10, 23 | EXPECTED_LIST_OR_OBJ = 11, 24 | NO_SUCH_FUNCTION = 12, 25 | DUPLICATE_VAR = 13, 26 | NO_SUCH_VAR = 14, 27 | USER_STR = 15, 28 | }; 29 | 30 | void expectedInt(); 31 | void expectedBool(); 32 | void expectedDouble(); 33 | void expectedStr(); 34 | void expectedList(); 35 | void expectedObj(); 36 | void expectedIntOrDouble(); 37 | void expectedStrOrInt(); 38 | void expectedStrOrIntOrDouble(); 39 | void expectedListOrStr(); 40 | void expectedListOrObj(); 41 | void noSuchFunction(); 42 | void duplicateVar(); 43 | void noSuchVar(); 44 | void errString(std::string msg); 45 | 46 | void throwError(ErrorCode code); 47 | 48 | void defaultHandle(ErrorCode code); 49 | 50 | } 51 | 52 | #endif 53 | -------------------------------------------------------------------------------- /scope.h: -------------------------------------------------------------------------------- 1 | #ifndef VAIVEN_VISITOR_HEADER_SCOPE 2 | #define VAIVEN_VISITOR_HEADER_SCOPE 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | using std::map; 10 | using std::string; 11 | using std::stack; 12 | using std::unordered_set; 13 | 14 | namespace vaiven { 15 | 16 | template 17 | class Scope; 18 | 19 | template 20 | class ScopeFrame { 21 | 22 | public: 23 | ScopeFrame(Scope& scope) : scope(scope) { 24 | scope.newFrame(); 25 | } 26 | 27 | ~ScopeFrame() { 28 | scope.endFrame(); 29 | } 30 | 31 | private: 32 | Scope& scope; 33 | }; 34 | 35 | template 36 | class Scope { 37 | public: 38 | Scope() { 39 | newFrame(); 40 | } 41 | 42 | void newFrame() { 43 | frames.push(unordered_set()); 44 | } 45 | 46 | void endFrame() { 47 | for (unordered_set::iterator it = frames.top().begin(); it != frames.top().end(); ++it) { 48 | currentVars.erase(*it); 49 | } 50 | 51 | frames.pop(); 52 | } 53 | 54 | void put(string name, V v) { 55 | if (currentVars.find(name) != currentVars.end()) { 56 | throw "already in scope"; 57 | } 58 | 59 | frames.top().insert(name); 60 | currentVars[name] = v; 61 | } 62 | 63 | void replace(string name, V v) { 64 | currentVars[name] = v; 65 | } 66 | 67 | bool contains(string name) { 68 | return currentVars.find(name) != currentVars.end(); 69 | } 70 | 71 | bool inHigherScope(string name) { 72 | return frames.top().find(name) == frames.top().end(); 73 | } 74 | 75 | V get(string name) { 76 | return currentVars[name]; 77 | } 78 | 79 | void fill(map& toFill) { 80 | toFill.insert(currentVars.begin(), currentVars.end()); 81 | } 82 | 83 | private: 84 | map currentVars; 85 | 86 | stack > frames; 87 | 88 | }; 89 | 90 | } 91 | 92 | #endif 93 | -------------------------------------------------------------------------------- /ssa/cfg.h: -------------------------------------------------------------------------------- 1 | #ifndef VAIVEN_VISITOR_HEADER_SSA_CFG 2 | #define VAIVEN_VISITOR_HEADER_SSA_CFG 3 | 4 | #include 5 | 6 | #include "ssa.h" 7 | 8 | using std::unique_ptr; 9 | 10 | namespace vaiven { namespace ssa { 11 | 12 | class BlockExit; 13 | 14 | class Block { 15 | public: 16 | Block() : head(), next() {}; 17 | 18 | asmjit::Label label; 19 | unique_ptr head; 20 | unique_ptr next; 21 | 22 | // don't use unordered set, harder to intersect 23 | set immPredecessors; 24 | set allPredecessors; 25 | set backReferences; 26 | set dominators; 27 | 28 | set loopHeaderWithBlocks; 29 | 30 | vector> exits; 31 | 32 | void accept(SsaVisitor& visitor) { 33 | visitor.visitBlock(*this); 34 | } 35 | }; 36 | 37 | enum BlockExitType { 38 | BLOCK_EXIT_UNCONDITIONAL, 39 | BLOCK_EXIT_CONDITIONAL, 40 | }; 41 | 42 | class BlockExit { 43 | public: 44 | BlockExit(BlockExitType tag, Block* toGoTo) : tag(tag), toGoTo(toGoTo) {}; 45 | virtual void accept(SsaVisitor& visitor)=0; 46 | virtual ~BlockExit() {}; 47 | BlockExitType tag; 48 | Block* toGoTo; 49 | }; 50 | 51 | class UnconditionalBlockExit : public BlockExit { 52 | public: 53 | UnconditionalBlockExit(Block* toGoTo) : BlockExit(BLOCK_EXIT_UNCONDITIONAL, toGoTo) {}; 54 | ~UnconditionalBlockExit() {}; 55 | virtual void accept(SsaVisitor& visitor) { 56 | visitor.visitUnconditionalBlockExit(*this); 57 | } 58 | }; 59 | 60 | class ConditionalBlockExit : public BlockExit { 61 | public: 62 | ConditionalBlockExit(Instruction* condition, Block* toGoTo) 63 | : condition(condition), BlockExit(BLOCK_EXIT_CONDITIONAL, toGoTo) {}; 64 | unique_ptr condition; 65 | ~ConditionalBlockExit() {}; 66 | 67 | virtual void accept(SsaVisitor& visitor) { 68 | visitor.visitConditionalBlockExit(*this); 69 | } 70 | }; 71 | 72 | } } 73 | 74 | #endif 75 | -------------------------------------------------------------------------------- /ssa/common_subexpression.h: -------------------------------------------------------------------------------- 1 | #ifndef VAIVEN_VISITOR_HEADER_SSA_COMMON_SUBEXPRESSION 2 | #define VAIVEN_VISITOR_HEADER_SSA_COMMON_SUBEXPRESSION 3 | 4 | #include 5 | 6 | #include "forward_visitor.h" 7 | #include "../value.h" 8 | 9 | namespace std { 10 | 11 | template<> 12 | struct hash { 13 | size_t operator()(vaiven::ssa::InstructionType const& type) const { 14 | return hash{}((int) type); 15 | } 16 | }; 17 | 18 | template<> 19 | struct hash { 20 | size_t operator()(vaiven::Value const& val) const { 21 | return hash{}(val.getRaw()); 22 | } 23 | }; 24 | 25 | template<> 26 | struct equal_to { 27 | bool operator()(vaiven::Value const& valA, vaiven::Value const& valB) const { 28 | return valA.getRaw() == valB.getRaw(); 29 | } 30 | }; 31 | 32 | template 33 | struct hash > { 34 | size_t operator()(pair const& vals) const { 35 | return hash{}(vals.first) * 31 + hash{}(vals.second); 36 | } 37 | }; 38 | 39 | template 40 | struct hash > { 41 | size_t operator()(vector const& vec) const { 42 | size_t acc = hash{}(vec.size()); 43 | 44 | for (auto it = vec.begin(); it != vec.end(); ++it) { 45 | acc *= 31; 46 | acc += hash{}(*it); 47 | } 48 | 49 | return acc; 50 | } 51 | }; 52 | } 53 | 54 | namespace vaiven { namespace ssa { 55 | 56 | class CommonSubexpressionEliminator : public ForwardVisitor { 57 | public: 58 | CommonSubexpressionEliminator() : performedWork(false) {}; 59 | 60 | void visitPhiInstr(PhiInstr& instr); 61 | void visitArgInstr(ArgInstr& instr); 62 | void visitConstantInstr(ConstantInstr& instr); 63 | void visitCallInstr(CallInstr& instr); 64 | void visitTypecheckInstr(TypecheckInstr& instr); 65 | void visitBoxInstr(BoxInstr& instr); 66 | void visitUnboxInstr(UnboxInstr& instr); 67 | void visitToDoubleInstr(ToDoubleInstr& instr); 68 | void visitIntToDoubleInstr(IntToDoubleInstr& instr); 69 | void visitAddInstr(AddInstr& instr); 70 | void visitIntAddInstr(IntAddInstr& instr); 71 | void visitDoubleAddInstr(DoubleAddInstr& instr); 72 | void visitStrAddInstr(StrAddInstr& instr); 73 | void visitSubInstr(SubInstr& instr); 74 | void visitIntSubInstr(IntSubInstr& instr); 75 | void visitDoubleSubInstr(DoubleSubInstr& instr); 76 | void visitMulInstr(MulInstr& instr); 77 | void visitIntMulInstr(IntMulInstr& instr); 78 | void visitDoubleMulInstr(DoubleMulInstr& instr); 79 | void visitDivInstr(DivInstr& instr); 80 | void visitNotInstr(NotInstr& instr); 81 | void visitCmpEqInstr(CmpEqInstr& instr); 82 | void visitIntCmpEqInstr(IntCmpEqInstr& instr); 83 | void visitDoubleCmpEqInstr(DoubleCmpEqInstr& instr); 84 | void visitCmpIneqInstr(CmpIneqInstr& instr); 85 | void visitIntCmpIneqInstr(IntCmpIneqInstr& instr); 86 | void visitDoubleCmpIneqInstr(DoubleCmpIneqInstr& instr); 87 | void visitCmpGtInstr(CmpGtInstr& instr); 88 | void visitIntCmpGtInstr(IntCmpGtInstr& instr); 89 | void visitDoubleCmpGtInstr(DoubleCmpGtInstr& instr); 90 | void visitCmpGteInstr(CmpGteInstr& instr); 91 | void visitIntCmpGteInstr(IntCmpGteInstr& instr); 92 | void visitDoubleCmpGteInstr(DoubleCmpGteInstr& instr); 93 | void visitCmpLtInstr(CmpLtInstr& instr); 94 | void visitIntCmpLtInstr(IntCmpLtInstr& instr); 95 | void visitDoubleCmpLtInstr(DoubleCmpLtInstr& instr); 96 | void visitCmpLteInstr(CmpLteInstr& instr); 97 | void visitIntCmpLteInstr(IntCmpLteInstr& instr); 98 | void visitDoubleCmpLteInstr(DoubleCmpLteInstr& instr); 99 | void visitDynamicAccessInstr(DynamicAccessInstr& instr); 100 | void visitDynamicStoreInstr(DynamicStoreInstr& instr); 101 | void visitListAccessInstr(ListAccessInstr& instr); 102 | void visitListStoreInstr(ListStoreInstr& instr); 103 | void visitListInitInstr(ListInitInstr& instr); 104 | void visitDynamicObjectAccessInstr(DynamicObjectAccessInstr& instr); 105 | void visitDynamicObjectStoreInstr(DynamicObjectStoreInstr& instr); 106 | void visitObjectAccessInstr(ObjectAccessInstr& instr); 107 | void visitObjectStoreInstr(ObjectStoreInstr& instr); 108 | void visitErrInstr(ErrInstr& instr); 109 | void visitRetInstr(RetInstr& instr); 110 | void visitJmpCcInstr(JmpCcInstr& instr); 111 | 112 | bool visitFoldableInstruction(Instruction& instr); 113 | 114 | bool performedWork; 115 | 116 | std::unordered_map >, std::vector > 117 | prevInstructions; 118 | std::unordered_map > constants; 119 | 120 | }; 121 | 122 | }} 123 | 124 | #endif 125 | -------------------------------------------------------------------------------- /ssa/constant_inliner.h: -------------------------------------------------------------------------------- 1 | #ifndef VAIVEN_VISITOR_HEADER_SSA_CONSTANT_INLINER 2 | #define VAIVEN_VISITOR_HEADER_SSA_CONSTANT_INLINER 3 | #include "forward_visitor.h" 4 | 5 | namespace vaiven { namespace ssa { 6 | 7 | class ConstantInliner : public ForwardVisitor { 8 | void visitPhiInstr(PhiInstr& instr); 9 | void visitArgInstr(ArgInstr& instr); 10 | void visitConstantInstr(ConstantInstr& instr); 11 | void visitCallInstr(CallInstr& instr); 12 | void visitTypecheckInstr(TypecheckInstr& instr); 13 | void visitBoxInstr(BoxInstr& instr); 14 | void visitUnboxInstr(UnboxInstr& instr); 15 | void visitToDoubleInstr(ToDoubleInstr& instr); 16 | void visitIntToDoubleInstr(IntToDoubleInstr& instr); 17 | void visitAddInstr(AddInstr& instr); 18 | void visitIntAddInstr(IntAddInstr& instr); 19 | void visitDoubleAddInstr(DoubleAddInstr& instr); 20 | void visitStrAddInstr(StrAddInstr& instr); 21 | void visitSubInstr(SubInstr& instr); 22 | void visitIntSubInstr(IntSubInstr& instr); 23 | void visitDoubleSubInstr(DoubleSubInstr& instr); 24 | void visitMulInstr(MulInstr& instr); 25 | void visitIntMulInstr(IntMulInstr& instr); 26 | void visitDoubleMulInstr(DoubleMulInstr& instr); 27 | void visitDivInstr(DivInstr& instr); 28 | void visitNotInstr(NotInstr& instr); 29 | void visitCmpEqInstr(CmpEqInstr& instr); 30 | void visitIntCmpEqInstr(IntCmpEqInstr& instr); 31 | void visitDoubleCmpEqInstr(DoubleCmpEqInstr& instr); 32 | void visitCmpIneqInstr(CmpIneqInstr& instr); 33 | void visitIntCmpIneqInstr(IntCmpIneqInstr& instr); 34 | void visitDoubleCmpIneqInstr(DoubleCmpIneqInstr& instr); 35 | void visitCmpGtInstr(CmpGtInstr& instr); 36 | void visitIntCmpGtInstr(IntCmpGtInstr& instr); 37 | void visitDoubleCmpGtInstr(DoubleCmpGtInstr& instr); 38 | void visitCmpGteInstr(CmpGteInstr& instr); 39 | void visitIntCmpGteInstr(IntCmpGteInstr& instr); 40 | void visitDoubleCmpGteInstr(DoubleCmpGteInstr& instr); 41 | void visitCmpLtInstr(CmpLtInstr& instr); 42 | void visitIntCmpLtInstr(IntCmpLtInstr& instr); 43 | void visitDoubleCmpLtInstr(DoubleCmpLtInstr& instr); 44 | void visitCmpLteInstr(CmpLteInstr& instr); 45 | void visitIntCmpLteInstr(IntCmpLteInstr& instr); 46 | void visitDoubleCmpLteInstr(DoubleCmpLteInstr& instr); 47 | void visitDynamicAccessInstr(DynamicAccessInstr& instr); 48 | void visitDynamicStoreInstr(DynamicStoreInstr& instr); 49 | void visitListAccessInstr(ListAccessInstr& instr); 50 | void visitListStoreInstr(ListStoreInstr& instr); 51 | void visitListInitInstr(ListInitInstr& instr); 52 | void visitDynamicObjectAccessInstr(DynamicObjectAccessInstr& instr); 53 | void visitDynamicObjectStoreInstr(DynamicObjectStoreInstr& instr); 54 | void visitObjectAccessInstr(ObjectAccessInstr& instr); 55 | void visitObjectStoreInstr(ObjectStoreInstr& instr); 56 | void visitErrInstr(ErrInstr& instr); 57 | void visitRetInstr(RetInstr& instr); 58 | void visitJmpCcInstr(JmpCcInstr& instr); 59 | }; 60 | 61 | }} 62 | 63 | #endif 64 | -------------------------------------------------------------------------------- /ssa/constant_propagation.h: -------------------------------------------------------------------------------- 1 | #ifndef VAIVEN_VISITOR_HEADER_SSA_CONSTANT_PROPAGATION 2 | #define VAIVEN_VISITOR_HEADER_SSA_CONSTANT_PROPAGATION 3 | #include "forward_visitor.h" 4 | 5 | namespace vaiven { namespace ssa { 6 | 7 | class ConstantPropagator : public ForwardVisitor { 8 | 9 | public: 10 | ConstantPropagator() : performedWork(false) {}; 11 | 12 | void visitPhiInstr(PhiInstr& instr); 13 | void visitArgInstr(ArgInstr& instr); 14 | void visitConstantInstr(ConstantInstr& instr); 15 | void visitCallInstr(CallInstr& instr); 16 | void visitTypecheckInstr(TypecheckInstr& instr); 17 | void visitBoxInstr(BoxInstr& instr); 18 | void visitUnboxInstr(UnboxInstr& instr); 19 | void visitToDoubleInstr(ToDoubleInstr& instr); 20 | void visitIntToDoubleInstr(IntToDoubleInstr& instr); 21 | void visitAddInstr(AddInstr& instr); 22 | void visitIntAddInstr(IntAddInstr& instr); 23 | void visitDoubleAddInstr(DoubleAddInstr& instr); 24 | void visitStrAddInstr(StrAddInstr& instr); 25 | void visitSubInstr(SubInstr& instr); 26 | void visitIntSubInstr(IntSubInstr& instr); 27 | void visitDoubleSubInstr(DoubleSubInstr& instr); 28 | void visitMulInstr(MulInstr& instr); 29 | void visitIntMulInstr(IntMulInstr& instr); 30 | void visitDoubleMulInstr(DoubleMulInstr& instr); 31 | void visitDivInstr(DivInstr& instr); 32 | void visitNotInstr(NotInstr& instr); 33 | void visitCmpEqInstr(CmpEqInstr& instr); 34 | void visitIntCmpEqInstr(IntCmpEqInstr& instr); 35 | void visitDoubleCmpEqInstr(DoubleCmpEqInstr& instr); 36 | void visitCmpIneqInstr(CmpIneqInstr& instr); 37 | void visitIntCmpIneqInstr(IntCmpIneqInstr& instr); 38 | void visitDoubleCmpIneqInstr(DoubleCmpIneqInstr& instr); 39 | void visitCmpGtInstr(CmpGtInstr& instr); 40 | void visitIntCmpGtInstr(IntCmpGtInstr& instr); 41 | void visitDoubleCmpGtInstr(DoubleCmpGtInstr& instr); 42 | void visitCmpGteInstr(CmpGteInstr& instr); 43 | void visitIntCmpGteInstr(IntCmpGteInstr& instr); 44 | void visitDoubleCmpGteInstr(DoubleCmpGteInstr& instr); 45 | void visitCmpLtInstr(CmpLtInstr& instr); 46 | void visitIntCmpLtInstr(IntCmpLtInstr& instr); 47 | void visitDoubleCmpLtInstr(DoubleCmpLtInstr& instr); 48 | void visitCmpLteInstr(CmpLteInstr& instr); 49 | void visitIntCmpLteInstr(IntCmpLteInstr& instr); 50 | void visitDoubleCmpLteInstr(DoubleCmpLteInstr& instr); 51 | void visitDynamicAccessInstr(DynamicAccessInstr& instr); 52 | void visitDynamicStoreInstr(DynamicStoreInstr& instr); 53 | void visitListAccessInstr(ListAccessInstr& instr); 54 | void visitListStoreInstr(ListStoreInstr& instr); 55 | void visitListInitInstr(ListInitInstr& instr); 56 | void visitDynamicObjectAccessInstr(DynamicObjectAccessInstr& instr); 57 | void visitDynamicObjectStoreInstr(DynamicObjectStoreInstr& instr); 58 | void visitObjectAccessInstr(ObjectAccessInstr& instr); 59 | void visitObjectStoreInstr(ObjectStoreInstr& instr); 60 | void visitErrInstr(ErrInstr& instr); 61 | void visitRetInstr(RetInstr& instr); 62 | void visitJmpCcInstr(JmpCcInstr& instr); 63 | 64 | bool isConstantBinInstruction(Instruction& instr); 65 | bool isConstantBinIntInstruction(Instruction& instr); 66 | void replaceWithConstant(Instruction& instr, Value newVal); 67 | void replace(Instruction& oldInstr, Instruction* newInstr); 68 | 69 | bool performedWork; 70 | }; 71 | 72 | }} 73 | 74 | #endif 75 | -------------------------------------------------------------------------------- /ssa/dominator_builder.cpp: -------------------------------------------------------------------------------- 1 | #include "dominator_builder.h" 2 | 3 | #include 4 | 5 | using namespace vaiven::ssa; 6 | 7 | void DominatorBuilder::firstBuild(Block& firstBlock) { 8 | Block* curBlock = &firstBlock; 9 | set visitedBlocks; 10 | 11 | while (true) { 12 | visitedBlocks.insert(curBlock); 13 | for (vector>::iterator it = curBlock->exits.begin(); 14 | it != curBlock->exits.end(); 15 | ++it) { 16 | 17 | if (visitedBlocks.find((*it)->toGoTo) != visitedBlocks.end()) { 18 | (*it)->toGoTo->backReferences.insert(curBlock); 19 | } else { 20 | (*it)->toGoTo->immPredecessors.insert(curBlock); 21 | } 22 | 23 | (*it)->toGoTo->allPredecessors.insert(curBlock); 24 | (*it)->toGoTo->allPredecessors.insert(curBlock->allPredecessors.begin(), 25 | curBlock->allPredecessors.end()); 26 | } 27 | 28 | if (curBlock->next.get() != NULL) { 29 | curBlock = curBlock->next.get(); 30 | } else { 31 | break; 32 | } 33 | } 34 | 35 | rebuild(firstBlock); 36 | } 37 | 38 | void DominatorBuilder::rebuild(Block& firstBlock) { 39 | Block* curBlock = &firstBlock; 40 | while (true) { 41 | rebuildBlock(curBlock); 42 | 43 | if (curBlock->next.get() != NULL) { 44 | curBlock = curBlock->next.get(); 45 | } else { 46 | break; 47 | } 48 | } 49 | 50 | } 51 | 52 | /** 53 | * At this point, we only know edges. We must be careful to traverse incoming 54 | * edges before back edges, as loop headers have multiple incoming edges but 55 | * still dominate the body of the loop (as opposed to places with multiple 56 | * forward edges, where only the union of the dominators dominate the subsequent 57 | * block). 58 | * 59 | * If -> IfTrue -> ForHeader -> ForBody 60 | * `--> IfFalse ---^ v ^----------' 61 | * ForEnd 62 | * 63 | * If dominates all blocks 64 | * ForHeader dominates ForBody, ForEnd 65 | * 66 | * If we recurse forward through the edges, 67 | */ 68 | void DominatorBuilder::rebuildBlock(Block* curBlock) { 69 | set incomingForwardEdges = curBlock->immPredecessors; 70 | 71 | if (incomingForwardEdges.size() == 0) { 72 | return; 73 | } 74 | 75 | // TODO this all assumes dominators have been built for the incoming 76 | // forward refs already. In theory should track unvisited blocks and visit 77 | // them in a stack (or use recursion). 78 | if (incomingForwardEdges.size() == 1) { 79 | Block* predecessor = *incomingForwardEdges.begin(); 80 | curBlock->dominators = predecessor->dominators; 81 | curBlock->dominators.insert(predecessor); 82 | } else { 83 | set::iterator it = incomingForwardEdges.begin(); 84 | curBlock->dominators = (*it)->dominators; 85 | set workingSet; 86 | 87 | for (++it; 88 | it != incomingForwardEdges.end(); 89 | ++it) { 90 | auto wsIt = set_intersection( 91 | curBlock->dominators.begin(), 92 | curBlock->dominators.end(), 93 | (*it)->dominators.begin(), 94 | (*it)->dominators.end(), 95 | inserter(workingSet, workingSet.begin())); 96 | 97 | curBlock->dominators = workingSet; 98 | } 99 | } 100 | 101 | for (vector>::iterator it = curBlock->exits.begin(); 102 | it != curBlock->exits.end(); 103 | ++it) { 104 | // loop detected! 105 | if (curBlock->dominators.find((*it)->toGoTo) != curBlock->dominators.end()) { 106 | Block* loopHeader = (*it)->toGoTo; 107 | set predecessorsFromLoopHeader; 108 | 109 | // find predecessors that hail from the loop header 110 | // NOTE: we could go from predecessors with loop header as a predecessor 111 | // to get blocks which MIGHT be in the loop. But for our purposes, w 112 | // get predecessors which ALWAYS hail from the loop. 113 | for (set::iterator pIt = curBlock->allPredecessors.begin(); 114 | pIt != curBlock->allPredecessors.end(); 115 | ++pIt) { 116 | set& pDominators = (*pIt)->dominators; 117 | if (pDominators.find(loopHeader) != pDominators.end()) { 118 | predecessorsFromLoopHeader.insert(*pIt); 119 | } 120 | } 121 | 122 | // find all blocks in the loop 123 | set workingSet; 124 | set_intersection( 125 | predecessorsFromLoopHeader.begin(), 126 | predecessorsFromLoopHeader.end(), 127 | loopHeader->allPredecessors.begin(), 128 | loopHeader->allPredecessors.end(), 129 | inserter(workingSet, workingSet.begin())); 130 | 131 | // note: the loop header may already have items, which is OK. 132 | loopHeader->loopHeaderWithBlocks.insert(workingSet.begin(), workingSet.end()); 133 | loopHeader->loopHeaderWithBlocks.insert(curBlock); 134 | } 135 | } 136 | } 137 | 138 | void DominatorBuilder::reset(Block& firstBlock) { 139 | Block* curBlock = &firstBlock; 140 | 141 | while (true) { 142 | curBlock->dominators.clear(); 143 | curBlock->allPredecessors.clear(); 144 | curBlock->loopHeaderWithBlocks.clear(); 145 | 146 | if (curBlock->next.get() != NULL) { 147 | curBlock = curBlock->next.get(); 148 | } else { 149 | break; 150 | } 151 | } 152 | 153 | curBlock = &firstBlock; 154 | // TODO, can allPredecessors be tracked incrementally or with a better 155 | // algorithm? 156 | while (true) { 157 | for (vector>::iterator it = curBlock->exits.begin(); 158 | it != curBlock->exits.end(); 159 | ++it) { 160 | (*it)->toGoTo->allPredecessors.insert(curBlock); 161 | (*it)->toGoTo->allPredecessors.insert(curBlock->allPredecessors.begin(), 162 | curBlock->allPredecessors.end()); 163 | 164 | // TODO do back references need updating? 165 | } 166 | 167 | if (curBlock->next.get() != NULL) { 168 | curBlock = curBlock->next.get(); 169 | } else { 170 | break; 171 | } 172 | } 173 | 174 | rebuild(firstBlock); 175 | } 176 | -------------------------------------------------------------------------------- /ssa/dominator_builder.h: -------------------------------------------------------------------------------- 1 | #ifndef VAIVEN_VISITOR_HEADER_SSA_DOMINATOR_BUILDER 2 | #define VAIVEN_VISITOR_HEADER_SSA_DOMINATOR_BUILDER 3 | #include "forward_visitor.h" 4 | 5 | #include 6 | #include 7 | 8 | using std::map; 9 | using std::set; 10 | 11 | namespace vaiven { namespace ssa { 12 | 13 | class DominatorBuilder { 14 | 15 | public: 16 | void firstBuild(Block& firstBlock); 17 | void rebuild(Block& firstBlock); 18 | 19 | void reset(Block& firstBlock); 20 | 21 | private: 22 | void rebuildBlock(Block* curBlock); 23 | }; 24 | 25 | }} 26 | 27 | #endif 28 | -------------------------------------------------------------------------------- /ssa/emitter.h: -------------------------------------------------------------------------------- 1 | #ifndef VAIVEN_VISITOR_HEADER_SSA_EMITTER 2 | #define VAIVEN_VISITOR_HEADER_SSA_EMITTER 3 | #include "forward_visitor.h" 4 | #include "../functions.h" 5 | #include "../error_compiler.h" 6 | 7 | namespace vaiven { namespace ssa { 8 | 9 | class Emitter : public ForwardVisitor { 10 | 11 | public: 12 | Emitter(asmjit::X86Compiler& cc, Functions& funcs, asmjit::Label funcLabel, string funcName, ErrorCompiler& error, asmjit::Label deoptimizeLabel) 13 | : cc(cc), funcs(funcs), funcLabel(funcLabel), funcName(funcName), error(error), deoptimizeLabel(deoptimizeLabel), afterGuardsLabel(funcLabel) {}; 14 | 15 | void visitPhiInstr(PhiInstr& instr); 16 | void visitArgInstr(ArgInstr& instr); 17 | void visitConstantInstr(ConstantInstr& instr); 18 | void visitCallInstr(CallInstr& instr); 19 | void visitTypecheckInstr(TypecheckInstr& instr); 20 | void visitBoxInstr(BoxInstr& instr); 21 | void visitUnboxInstr(UnboxInstr& instr); 22 | void visitToDoubleInstr(ToDoubleInstr& instr); 23 | void visitIntToDoubleInstr(IntToDoubleInstr& instr); 24 | void visitAddInstr(AddInstr& instr); 25 | void visitIntAddInstr(IntAddInstr& instr); 26 | void visitDoubleAddInstr(DoubleAddInstr& instr); 27 | void visitStrAddInstr(StrAddInstr& instr); 28 | void visitSubInstr(SubInstr& instr); 29 | void visitIntSubInstr(IntSubInstr& instr); 30 | void visitDoubleSubInstr(DoubleSubInstr& instr); 31 | void visitMulInstr(MulInstr& instr); 32 | void visitIntMulInstr(IntMulInstr& instr); 33 | void visitDoubleMulInstr(DoubleMulInstr& instr); 34 | void visitDivInstr(DivInstr& instr); 35 | void visitNotInstr(NotInstr& instr); 36 | void visitCmpEqInstr(CmpEqInstr& instr); 37 | void visitIntCmpEqInstr(IntCmpEqInstr& instr); 38 | void visitDoubleCmpEqInstr(DoubleCmpEqInstr& instr); 39 | void visitCmpIneqInstr(CmpIneqInstr& instr); 40 | void visitIntCmpIneqInstr(IntCmpIneqInstr& instr); 41 | void visitDoubleCmpIneqInstr(DoubleCmpIneqInstr& instr); 42 | void visitCmpGtInstr(CmpGtInstr& instr); 43 | void visitIntCmpGtInstr(IntCmpGtInstr& instr); 44 | void visitDoubleCmpGtInstr(DoubleCmpGtInstr& instr); 45 | void visitCmpGteInstr(CmpGteInstr& instr); 46 | void visitIntCmpGteInstr(IntCmpGteInstr& instr); 47 | void visitDoubleCmpGteInstr(DoubleCmpGteInstr& instr); 48 | void visitCmpLtInstr(CmpLtInstr& instr); 49 | void visitIntCmpLtInstr(IntCmpLtInstr& instr); 50 | void visitDoubleCmpLtInstr(DoubleCmpLtInstr& instr); 51 | void visitCmpLteInstr(CmpLteInstr& instr); 52 | void visitIntCmpLteInstr(IntCmpLteInstr& instr); 53 | void visitDoubleCmpLteInstr(DoubleCmpLteInstr& instr); 54 | void visitDynamicAccessInstr(DynamicAccessInstr& instr); 55 | void visitDynamicStoreInstr(DynamicStoreInstr& instr); 56 | void visitListAccessInstr(ListAccessInstr& instr); 57 | void visitListStoreInstr(ListStoreInstr& instr); 58 | void visitListInitInstr(ListInitInstr& instr); 59 | void visitDynamicObjectAccessInstr(DynamicObjectAccessInstr& instr); 60 | void visitDynamicObjectStoreInstr(DynamicObjectStoreInstr& instr); 61 | void visitObjectAccessInstr(ObjectAccessInstr& instr); 62 | void visitObjectStoreInstr(ObjectStoreInstr& instr); 63 | void doDoubleCmpInstr(Instruction& instr); 64 | void doIntCmpEqInstr(IntCmpEqInstr& instr); 65 | void doIntCmpIneqInstr(IntCmpIneqInstr& instr); 66 | void doIntCmpGtInstr(IntCmpGtInstr& instr); 67 | void doIntCmpGteInstr(IntCmpGteInstr& instr); 68 | void doIntCmpLtInstr(IntCmpLtInstr& instr); 69 | void doIntCmpLteInstr(IntCmpLteInstr& instr); 70 | void visitErrInstr(ErrInstr& instr); 71 | void visitRetInstr(RetInstr& instr); 72 | void visitJmpCcInstr(JmpCcInstr& instr); 73 | 74 | void visitUnconditionalBlockExit(UnconditionalBlockExit& exit); 75 | void visitConditionalBlockExit(ConditionalBlockExit& exit); 76 | void visitBlock(Block& block); 77 | 78 | ErrorCompiler& error; 79 | asmjit::X86Compiler& cc; 80 | asmjit::Label funcLabel; 81 | asmjit::Label deoptimizeLabel; 82 | asmjit::Label afterGuardsLabel; 83 | vector args; 84 | string funcName; 85 | Functions& funcs; 86 | }; 87 | 88 | }} 89 | 90 | #endif 91 | -------------------------------------------------------------------------------- /ssa/forward_visitor.cpp: -------------------------------------------------------------------------------- 1 | #include "forward_visitor.h" 2 | #include "cfg.h" 3 | 4 | using namespace vaiven::ssa; 5 | using std::unique_ptr; 6 | 7 | void ForwardVisitor::visitBlock(Block& block) { 8 | curBlock = █ 9 | lastInstr = NULL; 10 | Instruction* next = block.head.get(); 11 | while (next != NULL) { 12 | next->accept(*this); 13 | lastInstr = next; 14 | next = next->next; 15 | } 16 | 17 | for (vector>::iterator it = block.exits.begin(); 18 | it != block.exits.end(); 19 | ++it) { 20 | (*it)->accept(*this); 21 | } 22 | 23 | if (block.next != NULL) { 24 | block.next->accept(*this); 25 | } 26 | } 27 | 28 | void ForwardVisitor::visitUnconditionalBlockExit(UnconditionalBlockExit& exit) { 29 | // noop 30 | } 31 | 32 | void ForwardVisitor::visitConditionalBlockExit(ConditionalBlockExit& exit) { 33 | exit.condition->accept(*this); 34 | } 35 | -------------------------------------------------------------------------------- /ssa/forward_visitor.h: -------------------------------------------------------------------------------- 1 | #ifndef VAIVEN_VISITOR_HEADER_SSA_FORWARD_VISITOR 2 | #define VAIVEN_VISITOR_HEADER_SSA_FORWARD_VISITOR 3 | #include "cfg.h" 4 | 5 | namespace vaiven { namespace ssa { 6 | 7 | class ForwardVisitor : public SsaVisitor { 8 | 9 | public: 10 | ForwardVisitor() : curBlock(NULL), lastInstr(NULL) {}; 11 | 12 | virtual void visitPhiInstr(PhiInstr& instr)=0; 13 | virtual void visitArgInstr(ArgInstr& instr)=0; 14 | virtual void visitConstantInstr(ConstantInstr& instr)=0; 15 | virtual void visitCallInstr(CallInstr& instr)=0; 16 | virtual void visitTypecheckInstr(TypecheckInstr& instr)=0; 17 | virtual void visitBoxInstr(BoxInstr& instr)=0; 18 | virtual void visitUnboxInstr(UnboxInstr& instr)=0; 19 | virtual void visitToDoubleInstr(ToDoubleInstr& instr)=0; 20 | virtual void visitIntToDoubleInstr(IntToDoubleInstr& instr)=0; 21 | virtual void visitAddInstr(AddInstr& instr)=0; 22 | virtual void visitIntAddInstr(IntAddInstr& instr)=0; 23 | virtual void visitDoubleAddInstr(DoubleAddInstr& instr)=0; 24 | virtual void visitStrAddInstr(StrAddInstr& instr)=0; 25 | virtual void visitSubInstr(SubInstr& instr)=0; 26 | virtual void visitIntSubInstr(IntSubInstr& instr)=0; 27 | virtual void visitDoubleSubInstr(DoubleSubInstr& instr)=0; 28 | virtual void visitMulInstr(MulInstr& instr)=0; 29 | virtual void visitIntMulInstr(IntMulInstr& instr)=0; 30 | virtual void visitDivInstr(DivInstr& instr)=0; 31 | virtual void visitNotInstr(NotInstr& instr)=0; 32 | virtual void visitCmpEqInstr(CmpEqInstr& instr)=0; 33 | virtual void visitIntCmpEqInstr(IntCmpEqInstr& instr)=0; 34 | virtual void visitDoubleCmpEqInstr(DoubleCmpEqInstr& instr)=0; 35 | virtual void visitCmpIneqInstr(CmpIneqInstr& instr)=0; 36 | virtual void visitIntCmpIneqInstr(IntCmpIneqInstr& instr)=0; 37 | virtual void visitDoubleCmpIneqInstr(DoubleCmpIneqInstr& instr)=0; 38 | virtual void visitCmpGtInstr(CmpGtInstr& instr)=0; 39 | virtual void visitIntCmpGtInstr(IntCmpGtInstr& instr)=0; 40 | virtual void visitDoubleCmpGtInstr(DoubleCmpGtInstr& instr)=0; 41 | virtual void visitCmpGteInstr(CmpGteInstr& instr)=0; 42 | virtual void visitIntCmpGteInstr(IntCmpGteInstr& instr)=0; 43 | virtual void visitDoubleCmpGteInstr(DoubleCmpGteInstr& instr)=0; 44 | virtual void visitCmpLtInstr(CmpLtInstr& instr)=0; 45 | virtual void visitIntCmpLtInstr(IntCmpLtInstr& instr)=0; 46 | virtual void visitDoubleCmpLtInstr(DoubleCmpLtInstr& instr)=0; 47 | virtual void visitCmpLteInstr(CmpLteInstr& instr)=0; 48 | virtual void visitIntCmpLteInstr(IntCmpLteInstr& instr)=0; 49 | virtual void visitDoubleCmpLteInstr(DoubleCmpLteInstr& instr)=0; 50 | virtual void visitDynamicAccessInstr(DynamicAccessInstr& instr)=0; 51 | virtual void visitDynamicStoreInstr(DynamicStoreInstr& instr)=0; 52 | virtual void visitListAccessInstr(ListAccessInstr& instr)=0; 53 | virtual void visitListStoreInstr(ListStoreInstr& instr)=0; 54 | virtual void visitListInitInstr(ListInitInstr& instr)=0; 55 | virtual void visitDynamicObjectAccessInstr(DynamicObjectAccessInstr& instr)=0; 56 | virtual void visitDynamicObjectStoreInstr(DynamicObjectStoreInstr& instr)=0; 57 | virtual void visitObjectAccessInstr(ObjectAccessInstr& instr)=0; 58 | virtual void visitObjectStoreInstr(ObjectStoreInstr& instr)=0; 59 | virtual void visitErrInstr(ErrInstr& instr)=0; 60 | virtual void visitRetInstr(RetInstr& instr)=0; 61 | virtual void visitJmpCcInstr(JmpCcInstr& instr)=0; 62 | 63 | virtual void visitBlock(Block& block); 64 | virtual void visitUnconditionalBlockExit(UnconditionalBlockExit& exit); 65 | virtual void visitConditionalBlockExit(ConditionalBlockExit& exit); 66 | 67 | Block* curBlock; 68 | Instruction* lastInstr; 69 | }; 70 | 71 | }} 72 | 73 | #endif 74 | -------------------------------------------------------------------------------- /ssa/function_merge.cpp: -------------------------------------------------------------------------------- 1 | #include "function_merge.h" 2 | 3 | using namespace vaiven::ssa; 4 | 5 | void FunctionMerger::visitPhiInstr(PhiInstr& instr) { 6 | } 7 | 8 | void FunctionMerger::visitArgInstr(ArgInstr& instr) { 9 | } 10 | 11 | void FunctionMerger::visitConstantInstr(ConstantInstr& instr) { 12 | } 13 | 14 | void FunctionMerger::visitCallInstr(CallInstr& instr) { 15 | } 16 | 17 | void FunctionMerger::visitTypecheckInstr(TypecheckInstr& instr) { 18 | } 19 | 20 | void FunctionMerger::visitBoxInstr(BoxInstr& instr) { 21 | } 22 | 23 | void FunctionMerger::visitUnboxInstr(UnboxInstr& instr) { 24 | } 25 | 26 | void FunctionMerger::visitToDoubleInstr(ToDoubleInstr& instr) { 27 | } 28 | 29 | void FunctionMerger::visitIntToDoubleInstr(IntToDoubleInstr& instr) { 30 | } 31 | 32 | void FunctionMerger::visitAddInstr(AddInstr& instr) { 33 | } 34 | 35 | void FunctionMerger::visitStrAddInstr(StrAddInstr& instr) { 36 | } 37 | 38 | void FunctionMerger::visitIntAddInstr(IntAddInstr& instr) { 39 | } 40 | 41 | void FunctionMerger::visitDoubleAddInstr(DoubleAddInstr& instr) { 42 | } 43 | 44 | void FunctionMerger::visitSubInstr(SubInstr& instr) { 45 | } 46 | 47 | void FunctionMerger::visitIntSubInstr(IntSubInstr& instr) { 48 | } 49 | 50 | void FunctionMerger::visitDoubleSubInstr(DoubleSubInstr& instr) { 51 | } 52 | 53 | void FunctionMerger::visitMulInstr(MulInstr& instr) { 54 | } 55 | 56 | void FunctionMerger::visitIntMulInstr(IntMulInstr& instr) { 57 | } 58 | 59 | void FunctionMerger::visitDoubleMulInstr(DoubleMulInstr& instr) { 60 | } 61 | 62 | void FunctionMerger::visitDivInstr(DivInstr& instr) { 63 | } 64 | 65 | void FunctionMerger::visitNotInstr(NotInstr& instr) { 66 | } 67 | 68 | void FunctionMerger::visitCmpEqInstr(CmpEqInstr& instr) { 69 | } 70 | 71 | void FunctionMerger::visitIntCmpEqInstr(IntCmpEqInstr& instr) { 72 | } 73 | 74 | void FunctionMerger::visitDoubleCmpEqInstr(DoubleCmpEqInstr& instr) { 75 | } 76 | 77 | void FunctionMerger::visitCmpIneqInstr(CmpIneqInstr& instr) { 78 | } 79 | 80 | void FunctionMerger::visitIntCmpIneqInstr(IntCmpIneqInstr& instr) { 81 | } 82 | 83 | void FunctionMerger::visitDoubleCmpIneqInstr(DoubleCmpIneqInstr& instr) { 84 | } 85 | 86 | void FunctionMerger::visitCmpGtInstr(CmpGtInstr& instr) { 87 | } 88 | 89 | void FunctionMerger::visitIntCmpGtInstr(IntCmpGtInstr& instr) { 90 | } 91 | 92 | void FunctionMerger::visitDoubleCmpGtInstr(DoubleCmpGtInstr& instr) { 93 | } 94 | 95 | void FunctionMerger::visitCmpGteInstr(CmpGteInstr& instr) { 96 | } 97 | 98 | void FunctionMerger::visitIntCmpGteInstr(IntCmpGteInstr& instr) { 99 | } 100 | 101 | void FunctionMerger::visitDoubleCmpGteInstr(DoubleCmpGteInstr& instr) { 102 | } 103 | 104 | void FunctionMerger::visitCmpLtInstr(CmpLtInstr& instr) { 105 | } 106 | 107 | void FunctionMerger::visitIntCmpLtInstr(IntCmpLtInstr& instr) { 108 | } 109 | 110 | void FunctionMerger::visitDoubleCmpLtInstr(DoubleCmpLtInstr& instr) { 111 | } 112 | 113 | void FunctionMerger::visitCmpLteInstr(CmpLteInstr& instr) { 114 | } 115 | 116 | void FunctionMerger::visitIntCmpLteInstr(IntCmpLteInstr& instr) { 117 | } 118 | 119 | void FunctionMerger::visitDoubleCmpLteInstr(DoubleCmpLteInstr& instr) { 120 | } 121 | 122 | void FunctionMerger::visitDynamicAccessInstr(DynamicAccessInstr& instr) { 123 | } 124 | 125 | void FunctionMerger::visitDynamicStoreInstr(DynamicStoreInstr& instr) { 126 | } 127 | 128 | void FunctionMerger::visitListAccessInstr(ListAccessInstr& instr) { 129 | } 130 | 131 | void FunctionMerger::visitListStoreInstr(ListStoreInstr& instr) { 132 | } 133 | 134 | void FunctionMerger::visitListInitInstr(ListInitInstr& instr) { 135 | } 136 | 137 | void FunctionMerger::visitDynamicObjectAccessInstr(DynamicObjectAccessInstr& instr) { 138 | } 139 | 140 | void FunctionMerger::visitDynamicObjectStoreInstr(DynamicObjectStoreInstr& instr) { 141 | } 142 | 143 | void FunctionMerger::visitObjectAccessInstr(ObjectAccessInstr& instr) { 144 | } 145 | 146 | void FunctionMerger::visitObjectStoreInstr(ObjectStoreInstr& instr) { 147 | } 148 | 149 | void FunctionMerger::visitErrInstr(ErrInstr& instr) { 150 | } 151 | 152 | void FunctionMerger::visitRetInstr(RetInstr& instr) { 153 | phi->inputs.push_back(instr.inputs[0]); 154 | instr.inputs[0]->usages.insert(phi); 155 | if (lastInstr != NULL) { 156 | lastInstr->next = NULL; 157 | delete &instr; 158 | } else { 159 | curBlock->head.reset(NULL); 160 | } 161 | curBlock->exits.clear(); 162 | curBlock->exits.push_back(unique_ptr(new UnconditionalBlockExit(returnPoint))); 163 | } 164 | 165 | void FunctionMerger::visitJmpCcInstr(JmpCcInstr& instr) { 166 | } 167 | 168 | void FunctionMerger::visitBlock(Block& block) { 169 | curBlock = █ 170 | lastInstr = NULL; 171 | Instruction* next = block.head.get(); 172 | while (next != NULL) { 173 | next->accept(*this); 174 | // special cases: next was deleted 175 | if (lastInstr != NULL && lastInstr->next != next) { 176 | next = lastInstr->next; 177 | } else if (lastInstr == NULL && block.head.get() != next) { 178 | next = block.head.get(); 179 | } else { 180 | lastInstr = next; 181 | next = next->next; 182 | } 183 | } 184 | 185 | if (block.next != NULL) { 186 | block.next->accept(*this); 187 | } 188 | } 189 | -------------------------------------------------------------------------------- /ssa/function_merge.h: -------------------------------------------------------------------------------- 1 | #ifndef VAIVEN_VISITOR_HEADER_SSA_FUNCTION_MERGE 2 | #define VAIVEN_VISITOR_HEADER_SSA_FUNCTION_MERGE 3 | 4 | #include "forward_visitor.h" 5 | #include 6 | 7 | namespace vaiven { namespace ssa { 8 | 9 | class FunctionMerger : public ForwardVisitor { 10 | public: 11 | FunctionMerger(Block* returnPoint, PhiInstr* phi) : returnPoint(returnPoint), phi(phi) {}; 12 | 13 | void visitPhiInstr(PhiInstr& instr); 14 | void visitArgInstr(ArgInstr& instr); 15 | void visitConstantInstr(ConstantInstr& instr); 16 | void visitCallInstr(CallInstr& instr); 17 | void visitTypecheckInstr(TypecheckInstr& instr); 18 | void visitBoxInstr(BoxInstr& instr); 19 | void visitUnboxInstr(UnboxInstr& instr); 20 | void visitToDoubleInstr(ToDoubleInstr& instr); 21 | void visitIntToDoubleInstr(IntToDoubleInstr& instr); 22 | void visitAddInstr(AddInstr& instr); 23 | void visitIntAddInstr(IntAddInstr& instr); 24 | void visitDoubleAddInstr(DoubleAddInstr& instr); 25 | void visitStrAddInstr(StrAddInstr& instr); 26 | void visitSubInstr(SubInstr& instr); 27 | void visitIntSubInstr(IntSubInstr& instr); 28 | void visitDoubleSubInstr(DoubleSubInstr& instr); 29 | void visitMulInstr(MulInstr& instr); 30 | void visitIntMulInstr(IntMulInstr& instr); 31 | void visitDoubleMulInstr(DoubleMulInstr& instr); 32 | void visitDivInstr(DivInstr& instr); 33 | void visitNotInstr(NotInstr& instr); 34 | void visitCmpEqInstr(CmpEqInstr& instr); 35 | void visitIntCmpEqInstr(IntCmpEqInstr& instr); 36 | void visitDoubleCmpEqInstr(DoubleCmpEqInstr& instr); 37 | void visitCmpIneqInstr(CmpIneqInstr& instr); 38 | void visitIntCmpIneqInstr(IntCmpIneqInstr& instr); 39 | void visitDoubleCmpIneqInstr(DoubleCmpIneqInstr& instr); 40 | void visitCmpGtInstr(CmpGtInstr& instr); 41 | void visitIntCmpGtInstr(IntCmpGtInstr& instr); 42 | void visitDoubleCmpGtInstr(DoubleCmpGtInstr& instr); 43 | void visitCmpGteInstr(CmpGteInstr& instr); 44 | void visitIntCmpGteInstr(IntCmpGteInstr& instr); 45 | void visitDoubleCmpGteInstr(DoubleCmpGteInstr& instr); 46 | void visitCmpLtInstr(CmpLtInstr& instr); 47 | void visitIntCmpLtInstr(IntCmpLtInstr& instr); 48 | void visitDoubleCmpLtInstr(DoubleCmpLtInstr& instr); 49 | void visitCmpLteInstr(CmpLteInstr& instr); 50 | void visitIntCmpLteInstr(IntCmpLteInstr& instr); 51 | void visitDoubleCmpLteInstr(DoubleCmpLteInstr& instr); 52 | void visitDynamicAccessInstr(DynamicAccessInstr& instr); 53 | void visitDynamicStoreInstr(DynamicStoreInstr& instr); 54 | void visitListAccessInstr(ListAccessInstr& instr); 55 | void visitListStoreInstr(ListStoreInstr& instr); 56 | void visitListInitInstr(ListInitInstr& instr); 57 | void visitDynamicObjectAccessInstr(DynamicObjectAccessInstr& instr); 58 | void visitDynamicObjectStoreInstr(DynamicObjectStoreInstr& instr); 59 | void visitObjectAccessInstr(ObjectAccessInstr& instr); 60 | void visitObjectStoreInstr(ObjectStoreInstr& instr); 61 | void visitErrInstr(ErrInstr& instr); 62 | void visitRetInstr(RetInstr& instr); 63 | void visitJmpCcInstr(JmpCcInstr& instr); 64 | void visitBlock(Block& block); 65 | 66 | Block* returnPoint; 67 | PhiInstr* phi; 68 | }; 69 | 70 | }} 71 | 72 | #endif 73 | -------------------------------------------------------------------------------- /ssa/inliner.h: -------------------------------------------------------------------------------- 1 | #ifndef VAIVEN_VISITOR_HEADER_SSA_INLINER 2 | #define VAIVEN_VISITOR_HEADER_SSA_INLINER 3 | 4 | #include "forward_visitor.h" 5 | #include "../functions.h" 6 | #include 7 | 8 | namespace vaiven { namespace ssa { 9 | 10 | class Inliner : public ForwardVisitor { 11 | public: 12 | Inliner(Functions& funcs, int currentWorstSize) : funcs(funcs), currentWorstSize(currentWorstSize) {}; 13 | 14 | void visitPhiInstr(PhiInstr& instr); 15 | void visitArgInstr(ArgInstr& instr); 16 | void visitConstantInstr(ConstantInstr& instr); 17 | void visitCallInstr(CallInstr& instr); 18 | void visitTypecheckInstr(TypecheckInstr& instr); 19 | void visitBoxInstr(BoxInstr& instr); 20 | void visitUnboxInstr(UnboxInstr& instr); 21 | void visitToDoubleInstr(ToDoubleInstr& instr); 22 | void visitIntToDoubleInstr(IntToDoubleInstr& instr); 23 | void visitAddInstr(AddInstr& instr); 24 | void visitIntAddInstr(IntAddInstr& instr); 25 | void visitDoubleAddInstr(DoubleAddInstr& instr); 26 | void visitStrAddInstr(StrAddInstr& instr); 27 | void visitSubInstr(SubInstr& instr); 28 | void visitIntSubInstr(IntSubInstr& instr); 29 | void visitDoubleSubInstr(DoubleSubInstr& instr); 30 | void visitMulInstr(MulInstr& instr); 31 | void visitIntMulInstr(IntMulInstr& instr); 32 | void visitDoubleMulInstr(DoubleMulInstr& instr); 33 | void visitDivInstr(DivInstr& instr); 34 | void visitNotInstr(NotInstr& instr); 35 | void visitCmpEqInstr(CmpEqInstr& instr); 36 | void visitIntCmpEqInstr(IntCmpEqInstr& instr); 37 | void visitDoubleCmpEqInstr(DoubleCmpEqInstr& instr); 38 | void visitCmpIneqInstr(CmpIneqInstr& instr); 39 | void visitIntCmpIneqInstr(IntCmpIneqInstr& instr); 40 | void visitDoubleCmpIneqInstr(DoubleCmpIneqInstr& instr); 41 | void visitCmpGtInstr(CmpGtInstr& instr); 42 | void visitIntCmpGtInstr(IntCmpGtInstr& instr); 43 | void visitDoubleCmpGtInstr(DoubleCmpGtInstr& instr); 44 | void visitCmpGteInstr(CmpGteInstr& instr); 45 | void visitIntCmpGteInstr(IntCmpGteInstr& instr); 46 | void visitDoubleCmpGteInstr(DoubleCmpGteInstr& instr); 47 | void visitCmpLtInstr(CmpLtInstr& instr); 48 | void visitIntCmpLtInstr(IntCmpLtInstr& instr); 49 | void visitDoubleCmpLtInstr(DoubleCmpLtInstr& instr); 50 | void visitCmpLteInstr(CmpLteInstr& instr); 51 | void visitIntCmpLteInstr(IntCmpLteInstr& instr); 52 | void visitDoubleCmpLteInstr(DoubleCmpLteInstr& instr); 53 | void visitDynamicAccessInstr(DynamicAccessInstr& instr); 54 | void visitDynamicStoreInstr(DynamicStoreInstr& instr); 55 | void visitListAccessInstr(ListAccessInstr& instr); 56 | void visitListStoreInstr(ListStoreInstr& instr); 57 | void visitListInitInstr(ListInitInstr& instr); 58 | void visitDynamicObjectAccessInstr(DynamicObjectAccessInstr& instr); 59 | void visitDynamicObjectStoreInstr(DynamicObjectStoreInstr& instr); 60 | void visitObjectAccessInstr(ObjectAccessInstr& instr); 61 | void visitObjectStoreInstr(ObjectStoreInstr& instr); 62 | void visitErrInstr(ErrInstr& instr); 63 | void visitRetInstr(RetInstr& instr); 64 | void visitJmpCcInstr(JmpCcInstr& instr); 65 | void visitBlock(Block& block); 66 | 67 | Functions& funcs; 68 | int currentWorstSize; 69 | }; 70 | 71 | }} 72 | 73 | #endif 74 | -------------------------------------------------------------------------------- /ssa/instruction_combiner.h: -------------------------------------------------------------------------------- 1 | #ifndef VAIVEN_VISITOR_HEADER_SSA_INSTRUCTION_COMBINER 2 | #define VAIVEN_VISITOR_HEADER_SSA_INSTRUCTION_COMBINER 3 | #include "forward_visitor.h" 4 | 5 | namespace vaiven { namespace ssa { 6 | 7 | class InstructionCombiner : public ForwardVisitor { 8 | 9 | public: 10 | InstructionCombiner() : performedWork(false) {}; 11 | 12 | void visitPhiInstr(PhiInstr& instr); 13 | void visitArgInstr(ArgInstr& instr); 14 | void visitConstantInstr(ConstantInstr& instr); 15 | void visitCallInstr(CallInstr& instr); 16 | void visitTypecheckInstr(TypecheckInstr& instr); 17 | void visitBoxInstr(BoxInstr& instr); 18 | void visitUnboxInstr(UnboxInstr& instr); 19 | void visitToDoubleInstr(ToDoubleInstr& instr); 20 | void visitIntToDoubleInstr(IntToDoubleInstr& instr); 21 | void visitAddInstr(AddInstr& instr); 22 | void visitIntAddInstr(IntAddInstr& instr); 23 | void visitDoubleAddInstr(DoubleAddInstr& instr); 24 | void visitStrAddInstr(StrAddInstr& instr); 25 | void visitSubInstr(SubInstr& instr); 26 | void visitIntSubInstr(IntSubInstr& instr); 27 | void visitDoubleSubInstr(DoubleSubInstr& instr); 28 | void visitMulInstr(MulInstr& instr); 29 | void visitIntMulInstr(IntMulInstr& instr); 30 | void visitDoubleMulInstr(DoubleMulInstr& instr); 31 | void visitDivInstr(DivInstr& instr); 32 | void visitNotInstr(NotInstr& instr); 33 | void visitCmpEqInstr(CmpEqInstr& instr); 34 | void visitIntCmpEqInstr(IntCmpEqInstr& instr); 35 | void visitDoubleCmpEqInstr(DoubleCmpEqInstr& instr); 36 | void visitCmpIneqInstr(CmpIneqInstr& instr); 37 | void visitIntCmpIneqInstr(IntCmpIneqInstr& instr); 38 | void visitDoubleCmpIneqInstr(DoubleCmpIneqInstr& instr); 39 | void visitCmpGtInstr(CmpGtInstr& instr); 40 | void visitIntCmpGtInstr(IntCmpGtInstr& instr); 41 | void visitDoubleCmpGtInstr(DoubleCmpGtInstr& instr); 42 | void visitCmpGteInstr(CmpGteInstr& instr); 43 | void visitIntCmpGteInstr(IntCmpGteInstr& instr); 44 | void visitDoubleCmpGteInstr(DoubleCmpGteInstr& instr); 45 | void visitCmpLtInstr(CmpLtInstr& instr); 46 | void visitIntCmpLtInstr(IntCmpLtInstr& instr); 47 | void visitDoubleCmpLtInstr(DoubleCmpLtInstr& instr); 48 | void visitCmpLteInstr(CmpLteInstr& instr); 49 | void visitIntCmpLteInstr(IntCmpLteInstr& instr); 50 | void visitDoubleCmpLteInstr(DoubleCmpLteInstr& instr); 51 | void visitDynamicAccessInstr(DynamicAccessInstr& instr); 52 | void visitDynamicStoreInstr(DynamicStoreInstr& instr); 53 | void visitListAccessInstr(ListAccessInstr& instr); 54 | void visitListStoreInstr(ListStoreInstr& instr); 55 | void visitListInitInstr(ListInitInstr& instr); 56 | void visitDynamicObjectAccessInstr(DynamicObjectAccessInstr& instr); 57 | void visitDynamicObjectStoreInstr(DynamicObjectStoreInstr& instr); 58 | void visitObjectAccessInstr(ObjectAccessInstr& instr); 59 | void visitObjectStoreInstr(ObjectStoreInstr& instr); 60 | void visitErrInstr(ErrInstr& instr); 61 | void visitRetInstr(RetInstr& instr); 62 | void visitJmpCcInstr(JmpCcInstr& instr); 63 | 64 | bool isBinIntInstruction(Instruction& instr); 65 | void replaceReferencingNewConstant(Instruction& oldInstr, Instruction* newInstr); 66 | 67 | bool performedWork; 68 | }; 69 | 70 | }} 71 | 72 | #endif 73 | -------------------------------------------------------------------------------- /ssa/jmp_threader.h: -------------------------------------------------------------------------------- 1 | #ifndef VAIVEN_VISITOR_HEADER_SSA_JMP_THREADER 2 | #define VAIVEN_VISITOR_HEADER_SSA_JMP_THREADER 3 | #include "forward_visitor.h" 4 | #include "../functions.h" 5 | 6 | namespace vaiven { namespace ssa { 7 | 8 | class JmpThreader : public ForwardVisitor { 9 | 10 | public: 11 | JmpThreader() : requiresRebuildDominators(false) {}; 12 | 13 | void visitPhiInstr(PhiInstr& instr); 14 | void visitArgInstr(ArgInstr& instr); 15 | void visitConstantInstr(ConstantInstr& instr); 16 | void visitCallInstr(CallInstr& instr); 17 | void visitTypecheckInstr(TypecheckInstr& instr); 18 | void visitBoxInstr(BoxInstr& instr); 19 | void visitUnboxInstr(UnboxInstr& instr); 20 | void visitToDoubleInstr(ToDoubleInstr& instr); 21 | void visitIntToDoubleInstr(IntToDoubleInstr& instr); 22 | void visitAddInstr(AddInstr& instr); 23 | void visitIntAddInstr(IntAddInstr& instr); 24 | void visitDoubleAddInstr(DoubleAddInstr& instr); 25 | void visitStrAddInstr(StrAddInstr& instr); 26 | void visitSubInstr(SubInstr& instr); 27 | void visitIntSubInstr(IntSubInstr& instr); 28 | void visitDoubleSubInstr(DoubleSubInstr& instr); 29 | void visitMulInstr(MulInstr& instr); 30 | void visitIntMulInstr(IntMulInstr& instr); 31 | void visitDoubleMulInstr(DoubleMulInstr& instr); 32 | void visitDivInstr(DivInstr& instr); 33 | void visitNotInstr(NotInstr& instr); 34 | void visitCmpEqInstr(CmpEqInstr& instr); 35 | void visitIntCmpEqInstr(IntCmpEqInstr& instr); 36 | void visitDoubleCmpEqInstr(DoubleCmpEqInstr& instr); 37 | void visitCmpIneqInstr(CmpIneqInstr& instr); 38 | void visitIntCmpIneqInstr(IntCmpIneqInstr& instr); 39 | void visitDoubleCmpIneqInstr(DoubleCmpIneqInstr& instr); 40 | void visitCmpGtInstr(CmpGtInstr& instr); 41 | void visitIntCmpGtInstr(IntCmpGtInstr& instr); 42 | void visitDoubleCmpGtInstr(DoubleCmpGtInstr& instr); 43 | void visitCmpGteInstr(CmpGteInstr& instr); 44 | void visitIntCmpGteInstr(IntCmpGteInstr& instr); 45 | void visitDoubleCmpGteInstr(DoubleCmpGteInstr& instr); 46 | void visitCmpLtInstr(CmpLtInstr& instr); 47 | void visitIntCmpLtInstr(IntCmpLtInstr& instr); 48 | void visitDoubleCmpLtInstr(DoubleCmpLtInstr& instr); 49 | void visitCmpLteInstr(CmpLteInstr& instr); 50 | void visitIntCmpLteInstr(IntCmpLteInstr& instr); 51 | void visitDoubleCmpLteInstr(DoubleCmpLteInstr& instr); 52 | void visitDynamicAccessInstr(DynamicAccessInstr& instr); 53 | void visitDynamicStoreInstr(DynamicStoreInstr& instr); 54 | void visitListAccessInstr(ListAccessInstr& instr); 55 | void visitListStoreInstr(ListStoreInstr& instr); 56 | void visitListInitInstr(ListInitInstr& instr); 57 | void visitDynamicObjectAccessInstr(DynamicObjectAccessInstr& instr); 58 | void visitDynamicObjectStoreInstr(DynamicObjectStoreInstr& instr); 59 | void visitObjectAccessInstr(ObjectAccessInstr& instr); 60 | void visitObjectStoreInstr(ObjectStoreInstr& instr); 61 | void doCmpEqInstr(CmpEqInstr& instr); 62 | void doCmpIneqInstr(CmpIneqInstr& instr); 63 | void doCmpGtInstr(CmpGtInstr& instr); 64 | void doCmpGteInstr(CmpGteInstr& instr); 65 | void doCmpLtInstr(CmpLtInstr& instr); 66 | void doCmpLteInstr(CmpLteInstr& instr); 67 | void visitErrInstr(ErrInstr& instr); 68 | void visitRetInstr(RetInstr& instr); 69 | void visitJmpCcInstr(JmpCcInstr& instr); 70 | 71 | void visitConditionalBlockExit(ConditionalBlockExit& exit); 72 | void visitUnconditionalBlockExit(UnconditionalBlockExit& exit); 73 | 74 | bool requiresRebuildDominators; 75 | }; 76 | 77 | }} 78 | 79 | #endif 80 | -------------------------------------------------------------------------------- /ssa/loop_invariant.h: -------------------------------------------------------------------------------- 1 | #ifndef VAIVEN_VISITOR_HEADER_SSA_LOOP_INVARIANT 2 | #define VAIVEN_VISITOR_HEADER_SSA_LOOP_INVARIANT 3 | 4 | #include "forward_visitor.h" 5 | #include 6 | 7 | namespace vaiven { namespace ssa { 8 | 9 | class LoopInvariantCodeMover : public ForwardVisitor { 10 | public: 11 | LoopInvariantCodeMover() : requiresRebuildDominators(false), performedWork(false) {}; 12 | 13 | void visitPureInstruction(Instruction& instr); 14 | 15 | void visitPhiInstr(PhiInstr& instr); 16 | void visitArgInstr(ArgInstr& instr); 17 | void visitConstantInstr(ConstantInstr& instr); 18 | void visitCallInstr(CallInstr& instr); 19 | void visitTypecheckInstr(TypecheckInstr& instr); 20 | void visitBoxInstr(BoxInstr& instr); 21 | void visitUnboxInstr(UnboxInstr& instr); 22 | void visitToDoubleInstr(ToDoubleInstr& instr); 23 | void visitIntToDoubleInstr(IntToDoubleInstr& instr); 24 | void visitAddInstr(AddInstr& instr); 25 | void visitIntAddInstr(IntAddInstr& instr); 26 | void visitDoubleAddInstr(DoubleAddInstr& instr); 27 | void visitStrAddInstr(StrAddInstr& instr); 28 | void visitSubInstr(SubInstr& instr); 29 | void visitIntSubInstr(IntSubInstr& instr); 30 | void visitDoubleSubInstr(DoubleSubInstr& instr); 31 | void visitMulInstr(MulInstr& instr); 32 | void visitIntMulInstr(IntMulInstr& instr); 33 | void visitDoubleMulInstr(DoubleMulInstr& instr); 34 | void visitDivInstr(DivInstr& instr); 35 | void visitNotInstr(NotInstr& instr); 36 | void visitCmpEqInstr(CmpEqInstr& instr); 37 | void visitIntCmpEqInstr(IntCmpEqInstr& instr); 38 | void visitDoubleCmpEqInstr(DoubleCmpEqInstr& instr); 39 | void visitCmpIneqInstr(CmpIneqInstr& instr); 40 | void visitIntCmpIneqInstr(IntCmpIneqInstr& instr); 41 | void visitDoubleCmpIneqInstr(DoubleCmpIneqInstr& instr); 42 | void visitCmpGtInstr(CmpGtInstr& instr); 43 | void visitIntCmpGtInstr(IntCmpGtInstr& instr); 44 | void visitDoubleCmpGtInstr(DoubleCmpGtInstr& instr); 45 | void visitCmpGteInstr(CmpGteInstr& instr); 46 | void visitIntCmpGteInstr(IntCmpGteInstr& instr); 47 | void visitDoubleCmpGteInstr(DoubleCmpGteInstr& instr); 48 | void visitCmpLtInstr(CmpLtInstr& instr); 49 | void visitIntCmpLtInstr(IntCmpLtInstr& instr); 50 | void visitDoubleCmpLtInstr(DoubleCmpLtInstr& instr); 51 | void visitCmpLteInstr(CmpLteInstr& instr); 52 | void visitIntCmpLteInstr(IntCmpLteInstr& instr); 53 | void visitDoubleCmpLteInstr(DoubleCmpLteInstr& instr); 54 | void visitDynamicAccessInstr(DynamicAccessInstr& instr); 55 | void visitDynamicStoreInstr(DynamicStoreInstr& instr); 56 | void visitListAccessInstr(ListAccessInstr& instr); 57 | void visitListStoreInstr(ListStoreInstr& instr); 58 | void visitListInitInstr(ListInitInstr& instr); 59 | void visitDynamicObjectAccessInstr(DynamicObjectAccessInstr& instr); 60 | void visitDynamicObjectStoreInstr(DynamicObjectStoreInstr& instr); 61 | void visitObjectAccessInstr(ObjectAccessInstr& instr); 62 | void visitObjectStoreInstr(ObjectStoreInstr& instr); 63 | void visitErrInstr(ErrInstr& instr); 64 | void visitRetInstr(RetInstr& instr); 65 | void visitJmpCcInstr(JmpCcInstr& instr); 66 | void visitBlock(Block& block); 67 | 68 | Block* currentPreHeader; 69 | Instruction* writePoint; 70 | bool requiresRebuildDominators; 71 | bool performedWork; 72 | }; 73 | 74 | }} 75 | 76 | #endif 77 | -------------------------------------------------------------------------------- /ssa/print_visitor.h: -------------------------------------------------------------------------------- 1 | #ifndef VAIVEN_VISITOR_HEADER_SSA_PRINT_VISITOR 2 | #define VAIVEN_VISITOR_HEADER_SSA_PRINT_VISITOR 3 | 4 | #include "forward_visitor.h" 5 | #include 6 | 7 | namespace vaiven { namespace ssa { 8 | 9 | class PrintVisitor : public ForwardVisitor { 10 | public: 11 | int varId(Instruction* instr); 12 | void visitPhiInstr(PhiInstr& instr); 13 | void visitArgInstr(ArgInstr& instr); 14 | void visitConstantInstr(ConstantInstr& instr); 15 | void visitCallInstr(CallInstr& instr); 16 | void visitTypecheckInstr(TypecheckInstr& instr); 17 | void visitBoxInstr(BoxInstr& instr); 18 | void visitUnboxInstr(UnboxInstr& instr); 19 | void visitToDoubleInstr(ToDoubleInstr& instr); 20 | void visitIntToDoubleInstr(IntToDoubleInstr& instr); 21 | void visitAddInstr(AddInstr& instr); 22 | void visitIntAddInstr(IntAddInstr& instr); 23 | void visitDoubleAddInstr(DoubleAddInstr& instr); 24 | void visitStrAddInstr(StrAddInstr& instr); 25 | void visitSubInstr(SubInstr& instr); 26 | void visitIntSubInstr(IntSubInstr& instr); 27 | void visitDoubleSubInstr(DoubleSubInstr& instr); 28 | void visitMulInstr(MulInstr& instr); 29 | void visitIntMulInstr(IntMulInstr& instr); 30 | void visitDoubleMulInstr(DoubleMulInstr& instr); 31 | void visitDivInstr(DivInstr& instr); 32 | void visitNotInstr(NotInstr& instr); 33 | void visitCmpEqInstr(CmpEqInstr& instr); 34 | void visitIntCmpEqInstr(IntCmpEqInstr& instr); 35 | void visitDoubleCmpEqInstr(DoubleCmpEqInstr& instr); 36 | void visitCmpIneqInstr(CmpIneqInstr& instr); 37 | void visitIntCmpIneqInstr(IntCmpIneqInstr& instr); 38 | void visitDoubleCmpIneqInstr(DoubleCmpIneqInstr& instr); 39 | void visitCmpGtInstr(CmpGtInstr& instr); 40 | void visitIntCmpGtInstr(IntCmpGtInstr& instr); 41 | void visitDoubleCmpGtInstr(DoubleCmpGtInstr& instr); 42 | void visitCmpGteInstr(CmpGteInstr& instr); 43 | void visitIntCmpGteInstr(IntCmpGteInstr& instr); 44 | void visitDoubleCmpGteInstr(DoubleCmpGteInstr& instr); 45 | void visitCmpLtInstr(CmpLtInstr& instr); 46 | void visitIntCmpLtInstr(IntCmpLtInstr& instr); 47 | void visitDoubleCmpLtInstr(DoubleCmpLtInstr& instr); 48 | void visitCmpLteInstr(CmpLteInstr& instr); 49 | void visitIntCmpLteInstr(IntCmpLteInstr& instr); 50 | void visitDoubleCmpLteInstr(DoubleCmpLteInstr& instr); 51 | void visitDynamicAccessInstr(DynamicAccessInstr& instr); 52 | void visitDynamicStoreInstr(DynamicStoreInstr& instr); 53 | void visitListAccessInstr(ListAccessInstr& instr); 54 | void visitListStoreInstr(ListStoreInstr& instr); 55 | void visitListInitInstr(ListInitInstr& instr); 56 | void visitDynamicObjectAccessInstr(DynamicObjectAccessInstr& instr); 57 | void visitDynamicObjectStoreInstr(DynamicObjectStoreInstr& instr); 58 | void visitObjectAccessInstr(ObjectAccessInstr& instr); 59 | void visitObjectStoreInstr(ObjectStoreInstr& instr); 60 | void visitErrInstr(ErrInstr& instr); 61 | void visitRetInstr(RetInstr& instr); 62 | void visitJmpCcInstr(JmpCcInstr& instr); 63 | void visitBlock(Block& block); 64 | void visitUnconditionalBlockExit(UnconditionalBlockExit& exit); 65 | void visitConditionalBlockExit(ConditionalBlockExit& exit); 66 | 67 | std::map varIds; 68 | 69 | void printInstruction(std::string prefix, Instruction* instr); 70 | }; 71 | 72 | }} 73 | 74 | #endif 75 | -------------------------------------------------------------------------------- /ssa/reg_alloc.h: -------------------------------------------------------------------------------- 1 | #ifndef VAIVEN_VISITOR_HEADER_SSA_REG_ALLOC 2 | #define VAIVEN_VISITOR_HEADER_SSA_REG_ALLOC 3 | #include "ssa.h" 4 | #include "forward_visitor.h" 5 | 6 | #include "../asmjit/src/asmjit/asmjit.h" 7 | 8 | namespace vaiven { namespace ssa { 9 | 10 | class RegAlloc : public ForwardVisitor { 11 | 12 | public: 13 | RegAlloc(asmjit::X86Compiler& cc, vector argRegs) : cc(cc), argRegs(argRegs) {}; 14 | 15 | void visitPhiInstr(PhiInstr& instr); 16 | void visitArgInstr(ArgInstr& instr); 17 | void visitConstantInstr(ConstantInstr& instr); 18 | void visitCallInstr(CallInstr& instr); 19 | void visitTypecheckInstr(TypecheckInstr& instr); 20 | void visitBoxInstr(BoxInstr& instr); 21 | void visitUnboxInstr(UnboxInstr& instr); 22 | void visitToDoubleInstr(ToDoubleInstr& instr); 23 | void visitIntToDoubleInstr(IntToDoubleInstr& instr); 24 | void visitAddInstr(AddInstr& instr); 25 | void visitIntAddInstr(IntAddInstr& instr); 26 | void visitDoubleAddInstr(DoubleAddInstr& instr); 27 | void visitStrAddInstr(StrAddInstr& instr); 28 | void visitSubInstr(SubInstr& instr); 29 | void visitIntSubInstr(IntSubInstr& instr); 30 | void visitDoubleSubInstr(DoubleSubInstr& instr); 31 | void visitMulInstr(MulInstr& instr); 32 | void visitIntMulInstr(IntMulInstr& instr); 33 | void visitDoubleMulInstr(DoubleMulInstr& instr); 34 | void visitDivInstr(DivInstr& instr); 35 | void visitNotInstr(NotInstr& instr); 36 | void visitCmpEqInstr(CmpEqInstr& instr); 37 | void visitIntCmpEqInstr(IntCmpEqInstr& instr); 38 | void visitDoubleCmpEqInstr(DoubleCmpEqInstr& instr); 39 | void visitCmpIneqInstr(CmpIneqInstr& instr); 40 | void visitIntCmpIneqInstr(IntCmpIneqInstr& instr); 41 | void visitDoubleCmpIneqInstr(DoubleCmpIneqInstr& instr); 42 | void visitCmpGtInstr(CmpGtInstr& instr); 43 | void visitIntCmpGtInstr(IntCmpGtInstr& instr); 44 | void visitDoubleCmpGtInstr(DoubleCmpGtInstr& instr); 45 | void visitCmpGteInstr(CmpGteInstr& instr); 46 | void visitIntCmpGteInstr(IntCmpGteInstr& instr); 47 | void visitDoubleCmpGteInstr(DoubleCmpGteInstr& instr); 48 | void visitCmpLtInstr(CmpLtInstr& instr); 49 | void visitIntCmpLtInstr(IntCmpLtInstr& instr); 50 | void visitDoubleCmpLtInstr(DoubleCmpLtInstr& instr); 51 | void visitCmpLteInstr(CmpLteInstr& instr); 52 | void visitIntCmpLteInstr(IntCmpLteInstr& instr); 53 | void visitDoubleCmpLteInstr(DoubleCmpLteInstr& instr); 54 | void visitDynamicAccessInstr(DynamicAccessInstr& instr); 55 | void visitDynamicStoreInstr(DynamicStoreInstr& instr); 56 | void visitListAccessInstr(ListAccessInstr& instr); 57 | void visitListStoreInstr(ListStoreInstr& instr); 58 | void visitListInitInstr(ListInitInstr& instr); 59 | void visitDynamicObjectAccessInstr(DynamicObjectAccessInstr& instr); 60 | void visitDynamicObjectStoreInstr(DynamicObjectStoreInstr& instr); 61 | void visitObjectAccessInstr(ObjectAccessInstr& instr); 62 | void visitObjectStoreInstr(ObjectStoreInstr& instr); 63 | void visitErrInstr(ErrInstr& instr); 64 | void visitRetInstr(RetInstr& instr); 65 | void visitJmpCcInstr(JmpCcInstr& instr); 66 | 67 | void visitBlock(Block& block); 68 | 69 | private: 70 | vector argRegs; 71 | asmjit::X86Compiler& cc; 72 | void reuseInputRegIfPossible(Instruction& instr); 73 | }; 74 | 75 | }} 76 | 77 | #endif 78 | -------------------------------------------------------------------------------- /ssa/ssa.cpp: -------------------------------------------------------------------------------- 1 | #include "ssa.h" 2 | 3 | using namespace vaiven::ssa; 4 | 5 | void Instruction::replaceInput(Instruction* oldInstr, Instruction* newInstr) { 6 | for (vector::iterator it = inputs.begin(); 7 | it != inputs.end(); 8 | ++it) { 9 | if ((*it) == oldInstr) { 10 | *it = newInstr; 11 | } 12 | } 13 | 14 | // this happens during delete 15 | if (newInstr != NULL) { 16 | newInstr->usages.insert(this); 17 | } 18 | } 19 | 20 | void Instruction::replaceUsagesWith(Instruction* newInstr) { 21 | for (set::iterator it = usages.begin(); 22 | it != usages.end(); 23 | ++it) { 24 | (*it)->replaceInput(this, newInstr); 25 | } 26 | 27 | usages.clear(); 28 | } 29 | 30 | void Instruction::append(Instruction* toAppend) { 31 | toAppend->block = block; 32 | Instruction* toFollow = next; 33 | toAppend->next = toFollow; 34 | next = toAppend; 35 | } 36 | 37 | 38 | Instruction::~Instruction() { 39 | // have to be careful freeing, because there are a lot of 40 | // weak pointers that matter here. Take 41 | // ret foo; var x = y; if x do ret x; end 42 | // we delete 'var x' before 'ret x', since the `next` chain 43 | // doesn't cross block boundaries. 44 | // However, those are dead code, se we can replace the dangling 45 | // pointers with NULL and the freeing chain should work out. 46 | replaceUsagesWith(NULL); 47 | 48 | for (vector::iterator it = inputs.begin(); 49 | it != inputs.end(); 50 | ++it) { 51 | if (*it != NULL) { 52 | (*it)->usages.erase(this); 53 | } 54 | } 55 | 56 | if (next != NULL) { 57 | delete next; 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /ssa/type_analysis.h: -------------------------------------------------------------------------------- 1 | #ifndef VAIVEN_VISITOR_HEADER_SSA_TYPE_ANALYSIS 2 | #define VAIVEN_VISITOR_HEADER_SSA_TYPE_ANALYSIS 3 | #include "forward_visitor.h" 4 | 5 | namespace vaiven { namespace ssa { 6 | 7 | class TypeAnalysis : public ForwardVisitor { 8 | 9 | public: 10 | void visitPhiInstr(PhiInstr& instr); 11 | void visitArgInstr(ArgInstr& instr); 12 | void visitConstantInstr(ConstantInstr& instr); 13 | void visitCallInstr(CallInstr& instr); 14 | void visitTypecheckInstr(TypecheckInstr& instr); 15 | void visitBoxInstr(BoxInstr& instr); 16 | void visitUnboxInstr(UnboxInstr& instr); 17 | void visitToDoubleInstr(ToDoubleInstr& instr); 18 | void visitIntToDoubleInstr(IntToDoubleInstr& instr); 19 | void visitAddInstr(AddInstr& instr); 20 | void visitIntAddInstr(IntAddInstr& instr); 21 | void visitDoubleAddInstr(DoubleAddInstr& instr); 22 | void visitStrAddInstr(StrAddInstr& instr); 23 | void visitSubInstr(SubInstr& instr); 24 | void visitIntSubInstr(IntSubInstr& instr); 25 | void visitDoubleSubInstr(DoubleSubInstr& instr); 26 | void visitMulInstr(MulInstr& instr); 27 | void visitIntMulInstr(IntMulInstr& instr); 28 | void visitDoubleMulInstr(DoubleMulInstr& instr); 29 | void visitDivInstr(DivInstr& instr); 30 | void visitNotInstr(NotInstr& instr); 31 | void visitCmpEqInstr(CmpEqInstr& instr); 32 | void visitIntCmpEqInstr(IntCmpEqInstr& instr); 33 | void visitDoubleCmpEqInstr(DoubleCmpEqInstr& instr); 34 | void visitCmpIneqInstr(CmpIneqInstr& instr); 35 | void visitIntCmpIneqInstr(IntCmpIneqInstr& instr); 36 | void visitDoubleCmpIneqInstr(DoubleCmpIneqInstr& instr); 37 | void visitCmpGtInstr(CmpGtInstr& instr); 38 | void visitIntCmpGtInstr(IntCmpGtInstr& instr); 39 | void visitDoubleCmpGtInstr(DoubleCmpGtInstr& instr); 40 | void visitCmpGteInstr(CmpGteInstr& instr); 41 | void visitIntCmpGteInstr(IntCmpGteInstr& instr); 42 | void visitDoubleCmpGteInstr(DoubleCmpGteInstr& instr); 43 | void visitCmpLtInstr(CmpLtInstr& instr); 44 | void visitIntCmpLtInstr(IntCmpLtInstr& instr); 45 | void visitDoubleCmpLtInstr(DoubleCmpLtInstr& instr); 46 | void visitCmpLteInstr(CmpLteInstr& instr); 47 | void visitIntCmpLteInstr(IntCmpLteInstr& instr); 48 | void visitDoubleCmpLteInstr(DoubleCmpLteInstr& instr); 49 | void visitDynamicAccessInstr(DynamicAccessInstr& instr); 50 | void visitDynamicStoreInstr(DynamicStoreInstr& instr); 51 | void visitListAccessInstr(ListAccessInstr& instr); 52 | void visitListStoreInstr(ListStoreInstr& instr); 53 | void visitListInitInstr(ListInitInstr& instr); 54 | void visitDynamicObjectAccessInstr(DynamicObjectAccessInstr& instr); 55 | void visitDynamicObjectStoreInstr(DynamicObjectStoreInstr& instr); 56 | void visitObjectAccessInstr(ObjectAccessInstr& instr); 57 | void visitObjectStoreInstr(ObjectStoreInstr& instr); 58 | void visitErrInstr(ErrInstr& instr); 59 | void visitRetInstr(RetInstr& instr); 60 | void visitJmpCcInstr(JmpCcInstr& instr); 61 | 62 | void typecheckInput(Instruction& instr, VaivenStaticType expectedType, int input); 63 | void visitBinIntInstruction(Instruction& instr); 64 | void visitBinDoubleInstruction(Instruction& instr); 65 | void emit(Instruction* instr); 66 | void box(Instruction** input, Instruction* instr); 67 | 68 | }; 69 | 70 | }} 71 | 72 | #endif 73 | -------------------------------------------------------------------------------- /ssa/unused_code.h: -------------------------------------------------------------------------------- 1 | #ifndef VAIVEN_VISITOR_HEADER_SSA_UNUSED_CODE 2 | #define VAIVEN_VISITOR_HEADER_SSA_UNUSED_CODE 3 | #include "forward_visitor.h" 4 | 5 | #include 6 | #include 7 | 8 | using std::map; 9 | using std::set; 10 | 11 | namespace vaiven { namespace ssa { 12 | 13 | // TODO should be a backwards visitor... 14 | class UnusedCodeEliminator : public ForwardVisitor { 15 | 16 | public: 17 | UnusedCodeEliminator() : performedWork(false), requiresRebuildDominators(false) {}; 18 | 19 | void visitPhiInstr(PhiInstr& instr); 20 | void visitArgInstr(ArgInstr& instr); 21 | void visitConstantInstr(ConstantInstr& instr); 22 | void visitCallInstr(CallInstr& instr); 23 | void visitTypecheckInstr(TypecheckInstr& instr); 24 | void visitBoxInstr(BoxInstr& instr); 25 | void visitUnboxInstr(UnboxInstr& instr); 26 | void visitToDoubleInstr(ToDoubleInstr& instr); 27 | void visitIntToDoubleInstr(IntToDoubleInstr& instr); 28 | void visitAddInstr(AddInstr& instr); 29 | void visitIntAddInstr(IntAddInstr& instr); 30 | void visitDoubleAddInstr(DoubleAddInstr& instr); 31 | void visitStrAddInstr(StrAddInstr& instr); 32 | void visitSubInstr(SubInstr& instr); 33 | void visitIntSubInstr(IntSubInstr& instr); 34 | void visitDoubleSubInstr(DoubleSubInstr& instr); 35 | void visitMulInstr(MulInstr& instr); 36 | void visitIntMulInstr(IntMulInstr& instr); 37 | void visitDoubleMulInstr(DoubleMulInstr& instr); 38 | void visitDivInstr(DivInstr& instr); 39 | void visitNotInstr(NotInstr& instr); 40 | void visitCmpEqInstr(CmpEqInstr& instr); 41 | void visitIntCmpEqInstr(IntCmpEqInstr& instr); 42 | void visitDoubleCmpEqInstr(DoubleCmpEqInstr& instr); 43 | void visitCmpIneqInstr(CmpIneqInstr& instr); 44 | void visitIntCmpIneqInstr(IntCmpIneqInstr& instr); 45 | void visitDoubleCmpIneqInstr(DoubleCmpIneqInstr& instr); 46 | void visitCmpGtInstr(CmpGtInstr& instr); 47 | void visitIntCmpGtInstr(IntCmpGtInstr& instr); 48 | void visitDoubleCmpGtInstr(DoubleCmpGtInstr& instr); 49 | void visitCmpGteInstr(CmpGteInstr& instr); 50 | void visitIntCmpGteInstr(IntCmpGteInstr& instr); 51 | void visitDoubleCmpGteInstr(DoubleCmpGteInstr& instr); 52 | void visitCmpLtInstr(CmpLtInstr& instr); 53 | void visitIntCmpLtInstr(IntCmpLtInstr& instr); 54 | void visitDoubleCmpLtInstr(DoubleCmpLtInstr& instr); 55 | void visitCmpLteInstr(CmpLteInstr& instr); 56 | void visitIntCmpLteInstr(IntCmpLteInstr& instr); 57 | void visitDoubleCmpLteInstr(DoubleCmpLteInstr& instr); 58 | void visitDynamicAccessInstr(DynamicAccessInstr& instr); 59 | void visitDynamicStoreInstr(DynamicStoreInstr& instr); 60 | void visitListAccessInstr(ListAccessInstr& instr); 61 | void visitListStoreInstr(ListStoreInstr& instr); 62 | void visitListInitInstr(ListInitInstr& instr); 63 | void visitDynamicObjectAccessInstr(DynamicObjectAccessInstr& instr); 64 | void visitDynamicObjectStoreInstr(DynamicObjectStoreInstr& instr); 65 | void visitObjectAccessInstr(ObjectAccessInstr& instr); 66 | void visitObjectStoreInstr(ObjectStoreInstr& instr); 67 | void visitErrInstr(ErrInstr& instr); 68 | void visitRetInstr(RetInstr& instr); 69 | void visitJmpCcInstr(JmpCcInstr& instr); 70 | void visitConditionalBlockExit(ConditionalBlockExit& exit); 71 | void visitBlock(Block& block); 72 | 73 | bool performedWork; 74 | bool requiresRebuildDominators; 75 | 76 | void removeDeadCodeFromBlock(Block& block); 77 | void removeDeadExitsFromBlock(Block& block); 78 | void visitQueuedBlocks(); 79 | void removeUnusedBlocks(); 80 | void visitPureInstr(Instruction& instr); 81 | void remove(Instruction* instr); 82 | 83 | private: 84 | map backRefs; 85 | set reachableBlocks; 86 | set visitedBlocks; 87 | set allBlocks; 88 | set queuedBlocks; 89 | }; 90 | 91 | }} 92 | 93 | #endif 94 | -------------------------------------------------------------------------------- /stack.cpp: -------------------------------------------------------------------------------- 1 | #include "stack.h" 2 | 3 | #include "inttypes.h" 4 | 5 | using namespace vaiven; 6 | 7 | vaiven::StackFrame::StackFrame(uint64_t* prevRbp) { 8 | rbp = (uint64_t*) *prevRbp; 9 | retaddr = *(rbp + 8); 10 | locals = rbp - 8; 11 | uint64_t* lastLocal = prevRbp + 16; 12 | size = locals - lastLocal; 13 | locals = lastLocal; // so we can use locals[0], locals[1], ... 14 | } 15 | 16 | StackFrame vaiven::StackFrame::next() { 17 | return StackFrame(rbp); 18 | } 19 | 20 | bool vaiven::StackFrame::hasNext() { 21 | return *rbp != 0; 22 | } 23 | 24 | uint64_t* __attribute__ ((noinline)) vaiven::Stack::rbp() { 25 | asm("mov (%rbp), %rax"); 26 | } 27 | 28 | StackFrame vaiven::Stack::top() { 29 | return StackFrame(rbp()); 30 | } 31 | -------------------------------------------------------------------------------- /stack.h: -------------------------------------------------------------------------------- 1 | #ifndef VAIVEN_VISITOR_HEADER_STACK 2 | #define VAIVEN_VISITOR_HEADER_STACK 3 | 4 | #include "inttypes.h" 5 | 6 | namespace vaiven { 7 | 8 | class StackFrame { 9 | public: 10 | StackFrame(uint64_t* prevRbp); 11 | 12 | int size; 13 | uint64_t* rbp; 14 | uint64_t* locals; 15 | uint64_t retaddr; 16 | 17 | StackFrame next(); 18 | bool hasNext(); 19 | }; 20 | 21 | class Stack { 22 | public: 23 | StackFrame top(); 24 | 25 | private: 26 | uint64_t* rbp(); 27 | }; 28 | 29 | } 30 | 31 | #endif 32 | -------------------------------------------------------------------------------- /std.h: -------------------------------------------------------------------------------- 1 | #ifndef VAIVEN_VISITOR_HEADER_STD 2 | #define VAIVEN_VISITOR_HEADER_STD 3 | 4 | #include "functions.h" 5 | #include "heap.h" 6 | 7 | namespace vaiven { 8 | 9 | void init_std(Functions& funcs); 10 | 11 | // exposed to vaiven code 12 | Value print(Value value); 13 | Value append(Value lhs, Value rhs); 14 | Value len(Value subject); 15 | Value assert(Value expectation); 16 | Value object(); 17 | Value keys(Value object); 18 | Value toString(Value subject); 19 | Value sqrt(Value value); 20 | Value round(Value value); 21 | Value floor(Value value); 22 | Value ceil(Value value); 23 | 24 | // used by interpreter/called by assembly 25 | Value newList(); 26 | Value newListWithSize(int size); 27 | Value* getListContainerUnchecked(GcableList* list); 28 | Value add(Value lhs, Value rhs); 29 | Value sub(Value lhs, Value rhs); 30 | Value mul(Value lhs, Value rhs); 31 | Value div(Value lhs, Value rhs); 32 | Value gt(Value lhs, Value rhs); 33 | Value gte(Value lhs, Value rhs); 34 | Value lt(Value lhs, Value rhs); 35 | Value lte(Value lhs, Value rhs); 36 | Value addStrUnchecked(GcableString* lhs, GcableString* rhs); 37 | Value set(Value objectOrArr, Value propOrIndex, Value value); 38 | Value get(Value objectOrArr, Value propOrIndex); 39 | Value listAccessUnchecked(GcableList* list, int index); 40 | void listStoreUnchecked(GcableList* list, int index, Value value); 41 | Value objectAccessChecked(Value subject, string& property); 42 | void objectStoreChecked(Value subject, string& property, Value value); 43 | Value objectAccessUnchecked(GcableObject* object, string& property); 44 | void objectStoreUnchecked(GcableObject* object, string& property, Value value); 45 | Value cmp(Value a, Value b); 46 | Value inverseCmp(Value a, Value b); 47 | // seems like using bool often results in garbage in the upper bits 48 | uint64_t cmpUnboxed(Value a, Value b); 49 | uint64_t cmpStrUnchecked(GcableString* a, GcableString* b); 50 | uint64_t inverseCmpUnboxed(Value a, Value b); 51 | uint64_t inverseCmpStrUnchecked(GcableString* a, GcableString* b); 52 | string toStringCpp(Value subject); 53 | 54 | } 55 | 56 | #endif 57 | -------------------------------------------------------------------------------- /test/assemble/instruction_combiner.vvn: -------------------------------------------------------------------------------- 1 | fn plusOneEq of x is 2 | x + 1 == 2 3 | end 4 | 5 | fn plusOneIneq of x is 6 | x + 1 != 2 7 | end 8 | 9 | fn subOneEq of x is 10 | x - 1 == 2 11 | end 12 | 13 | fn subOneIneq of x is 14 | x - 1 != 2 15 | end 16 | 17 | fn fiveSubEq of x is 18 | 5 - x == 2 19 | end 20 | 21 | fn fiveSubIneq of x is 22 | 5 - x != 2 23 | end 24 | 25 | fn mulTwoEq of x is 26 | x * 2 == 2 27 | end 28 | 29 | fn mulTwoIneq of x is 30 | x * 2 != 2 31 | end 32 | 33 | fn integerMath of x is 34 | var zero = x - x 35 | var twox = x + x 36 | var fourx = twox * 2 37 | var twoxmul = x * 2 38 | var fourxmul = 2 * twoxmul * 1 39 | var zerotwo = fourx - fourxmul 40 | var zerothree = zero - zerotwo 41 | var two = 2 - zerothree 42 | ret 4 + two + 4 - 4 - 4 - 2 43 | end 44 | 45 | var x = 0 46 | for x < 20 47 | assert(integerMath(x) == 0) 48 | assert(plusOneEq(1) == true) 49 | assert(plusOneEq(0) == false) 50 | assert(plusOneIneq(1) == false) 51 | assert(plusOneIneq(0) == true) 52 | assert(subOneEq(3) == true) 53 | assert(subOneEq(2) == false) 54 | assert(subOneIneq(3) == false) 55 | assert(subOneIneq(2) == true) 56 | assert(fiveSubEq(3) == true) 57 | assert(fiveSubEq(2) == false) 58 | assert(fiveSubIneq(3) == false) 59 | assert(fiveSubIneq(2) == true) 60 | assert(mulTwoEq(1) == true) 61 | assert(mulTwoEq(2) == false) 62 | assert(mulTwoIneq(1) == false) 63 | assert(mulTwoIneq(0) == true) 64 | x += 1 65 | end 66 | -------------------------------------------------------------------------------- /test/assemble/lists.vvn: -------------------------------------------------------------------------------- 1 | fn test of varSoItCanOptimize is 2 | assert(toString([]) == "[]") 3 | assert(toString([][0]) == "void") 4 | assert(toString([][3]) == "void") 5 | 6 | assert(toString([1]) == "[1]") 7 | assert([1][0] == 1) 8 | assert(toString([1][1]) == "void") 9 | assert(toString([1][3]) == "void") 10 | 11 | assert(toString([1, 2]) == "[1, 2]") 12 | assert([1, 2][0] == 1) 13 | assert([1, 2][1] == 2) 14 | assert(toString([1, 2][2]) == "void") 15 | assert(toString([1, 2][3]) == "void") 16 | 17 | assert(toString([1, [], 2]) == "[1, [], 2]") 18 | assert([1, [], 2][0] == 1) 19 | assert(toString([1, [], 2][1]) == "[]") 20 | assert([1, [], 2][2] == 2) 21 | assert(toString([1, 2][3]) == "void") 22 | assert(toString([1, 2][5]) == "void") 23 | 24 | var list = [1, 2] 25 | assert(toString(list) == "[1, 2]") 26 | assert(list[0] == 1) 27 | assert(list[1] == 2) 28 | assert(toString([list]) == "[[1, 2]]") 29 | assert([list][0] == list); 30 | assert([list][0][0] == 1); 31 | assert([list][0][1] == 2); 32 | 33 | var i = 0 34 | var shouldBeNew = []; 35 | for i < 10 36 | shouldBeNew = [1, 2] 37 | assert(toString(shouldBeNew) == "[1, 2]") 38 | append(shouldBeNew, 3) 39 | assert(toString(shouldBeNew) == "[1, 2, 3]") 40 | i = i + 1 41 | end 42 | end 43 | 44 | test() 45 | test() 46 | test() 47 | test() 48 | test() 49 | test() 50 | test() 51 | test() 52 | -------------------------------------------------------------------------------- /test/assemble/modeq.vvn: -------------------------------------------------------------------------------- 1 | fn inc of observable, retval is 2 | observable[0] += 1 3 | ret retval 4 | end 5 | 6 | fn run of varSoOptimizes is 7 | var x = 1 8 | 9 | assert((x += 2) == 3) 10 | assert(x == 3) 11 | 12 | assert((x -= 1) == 2) 13 | assert(x == 2) 14 | 15 | assert((x *= 2) == 4) 16 | assert(x == 4) 17 | 18 | assert((x /= 2) == 2) 19 | assert(x == 2) 20 | 21 | x = "foo" 22 | 23 | assert((x += "bar") == "foobar") 24 | assert(x == "foobar") 25 | 26 | x = [1] 27 | 28 | var observable = [0] 29 | assert((x[inc(observable, 0)] += 3) == 4) 30 | assert(x[0] == 4) 31 | assert(observable[0] == 1) 32 | 33 | var o = object() 34 | 35 | o.foo = "foo" 36 | 37 | assert((inc(observable, o).foo += "bar") == "foobar") 38 | assert(o.foo == "foobar") 39 | assert(observable[0] == 2) 40 | end 41 | 42 | run() 43 | "make hot" 44 | run() 45 | run() 46 | run() 47 | run() 48 | run() 49 | run() 50 | run() 51 | run() 52 | -------------------------------------------------------------------------------- /test/assemble/objects.vvn: -------------------------------------------------------------------------------- 1 | fn run of varSoItOptimizes is 2 | var o = object(); 3 | 4 | assert(o.foo == void) 5 | assert(o.bar == void) 6 | assert(o["foo"] == void) 7 | assert(o["bar"] == void) 8 | 9 | o.foo = 4 10 | 11 | assert(o.foo == 4) 12 | assert(o.bar == void) 13 | assert(o["foo"] == 4) 14 | assert(o["bar"] == void) 15 | 16 | o.foo = 4 17 | 18 | assert(o.foo == 4) 19 | assert(o.bar == void) 20 | assert(o["foo"] == 4) 21 | assert(o["bar"] == void) 22 | 23 | assert((o.foo = "bar") == "bar") 24 | assert(o.foo == "bar") 25 | assert(o.bar == void) 26 | assert(o["foo"] == "bar") 27 | assert(o["bar"] == void) 28 | 29 | o.bar = 4 30 | 31 | assert(o.foo == "bar") 32 | assert(o.bar == 4) 33 | assert(o["foo"] == "bar") 34 | assert(o["bar"] == 4) 35 | 36 | assert((o["baz"] = "bang") == "bang") 37 | assert(o.foo == "bar") 38 | assert(o.bar == 4) 39 | assert(o.baz == "bang") 40 | assert(o["foo"] == "bar") 41 | assert(o["bar"] == 4) 42 | assert(o["baz"] == "bang") 43 | end 44 | 45 | run() 46 | "make hot" 47 | run() 48 | run() 49 | run() 50 | run() 51 | run() 52 | run() 53 | run() 54 | -------------------------------------------------------------------------------- /test/assemble/strings.vvn: -------------------------------------------------------------------------------- 1 | fn isFoo of str is 2 | "foo" == str 3 | end 4 | 5 | fn isFour of str is 6 | str == 4 7 | end 8 | 9 | fn isTrue of str is 10 | str == true 11 | end 12 | 13 | fn isFalse of str is 14 | str == false 15 | end 16 | 17 | fn isList of str is 18 | str == [] 19 | end 20 | 21 | fn isObject of str is 22 | str == object() 23 | end 24 | 25 | fn basicStrOps 26 | assert("foo" == "foo") 27 | assert("foo" != "fo") 28 | assert("foo" == "fo" + "o") 29 | assert(!isFour("foo")) 30 | assert(!isTrue("foo")) 31 | assert(!isFalse("foo")) 32 | assert(!isList("foo")) 33 | assert(!isObject("foo")) 34 | assert("foo" != 4) 35 | assert("foo" != true) 36 | assert("foo" != false) 37 | assert("foo" != []) 38 | assert("foo" != object()) 39 | assert(isFoo("foo")) 40 | assert(isFoo("fo" + "o")) 41 | assert(isFoo("f" + "o" + "o")) 42 | assert(!isFoo("fo")) 43 | assert(!isFoo(true)) 44 | assert(!isFoo(false)) 45 | assert(!isFoo([])) 46 | assert(!isFoo(object())) 47 | end 48 | 49 | "make it hot" 50 | basicStrOps() 51 | basicStrOps() 52 | basicStrOps() 53 | basicStrOps() 54 | basicStrOps() 55 | basicStrOps() 56 | basicStrOps() 57 | basicStrOps() 58 | basicStrOps() 59 | basicStrOps() 60 | basicStrOps() 61 | basicStrOps() 62 | basicStrOps() 63 | -------------------------------------------------------------------------------- /test/deoptimize/ints.vvn: -------------------------------------------------------------------------------- 1 | fn intOp of x is 2 | x * 10 3 | end 4 | 5 | "make hot" 6 | intOp(1) 7 | intOp(1) 8 | intOp(1) 9 | intOp(1) 10 | 11 | intOp(true) 12 | intOp(false) 13 | intOp() 14 | intOp("foo") 15 | intOp([]) 16 | intOp(object()) 17 | 18 | fn intAdd of x is 19 | x + x 20 | end 21 | 22 | "make hot" 23 | intAdd(1) 24 | intAdd(1) 25 | intAdd(1) 26 | intAdd(1) 27 | 28 | intAdd(true) 29 | intAdd(false) 30 | intAdd() 31 | intAdd([]) 32 | intAdd(object()) 33 | 34 | assert(intAdd("foo") == "foofoo") 35 | 36 | fn intCmp of x, y is 37 | x == y 38 | end 39 | 40 | "make hot" 41 | intCmp(1, 1) 42 | intCmp(1, 1) 43 | intCmp(1, 1) 44 | intCmp(1, 1) 45 | 46 | assert(intCmp("foo", "foo") == true) 47 | -------------------------------------------------------------------------------- /test/deoptimize/ints.vvn_expectederrors: -------------------------------------------------------------------------------- 1 | Error: Got a wrong type in an operation for ints/doubles 2 | Error: Got a wrong type in an operation for ints/doubles 3 | Error: Got a wrong type in an operation for ints/doubles 4 | Error: Got a wrong type in an operation for ints/doubles 5 | Error: Got a wrong type in an operation for ints/doubles 6 | Error: Got a wrong type in an operation for ints/doubles 7 | Error: Got a wrong type in an operation for ints/strings/doubles 8 | Error: Got a wrong type in an operation for ints/strings/doubles 9 | Error: Got a wrong type in an operation for ints/strings/doubles 10 | Error: Got a wrong type in an operation for ints/strings/doubles 11 | Error: Got a wrong type in an operation for ints/strings/doubles 12 | -------------------------------------------------------------------------------- /test/deoptimize/strings.vvn: -------------------------------------------------------------------------------- 1 | fn strOp of x is 2 | x + "foo" 3 | end 4 | 5 | "make hot" 6 | strOp("foo") 7 | strOp("foo") 8 | strOp("foo") 9 | strOp("foo") 10 | strOp("foo") 11 | strOp("foo") 12 | strOp("foo") 13 | strOp("foo") 14 | strOp("foo") 15 | strOp("foo") 16 | strOp("foo") 17 | strOp("foo") 18 | strOp("foo") 19 | strOp("foo") 20 | strOp("foo") 21 | 22 | strOp(4) 23 | strOp(true) 24 | strOp(false) 25 | strOp() 26 | strOp([]) 27 | strOp(object()) 28 | 29 | fn strAdd of x is 30 | x + x 31 | end 32 | 33 | "make hot" 34 | strAdd("foo") 35 | strAdd("foo") 36 | strAdd("foo") 37 | strAdd("foo") 38 | strAdd("foo") 39 | strAdd("foo") 40 | strAdd("foo") 41 | strAdd("foo") 42 | strAdd("foo") 43 | strAdd("foo") 44 | strAdd("foo") 45 | strAdd("foo") 46 | strAdd("foo") 47 | strAdd("foo") 48 | strAdd("foo") 49 | strAdd("foo") 50 | strAdd("foo") 51 | strAdd("foo") 52 | strAdd("foo") 53 | strAdd("foo") 54 | 55 | assert(strAdd(4) == 8) 56 | 57 | strAdd(true) 58 | strAdd(false) 59 | strAdd() 60 | strAdd([]) 61 | strAdd(object()) 62 | 63 | fn strCmp of x, y is 64 | x == y 65 | end 66 | 67 | "make hot" 68 | strCmp("foo", "foo") 69 | strCmp("foo", "foo") 70 | strCmp("foo", "foo") 71 | strCmp("foo", "foo") 72 | strCmp("foo", "foo") 73 | strCmp("foo", "foo") 74 | strCmp("foo", "foo") 75 | strCmp("foo", "foo") 76 | strCmp("foo", "foo") 77 | strCmp("foo", "foo") 78 | strCmp("foo", "foo") 79 | strCmp("foo", "foo") 80 | strCmp("foo", "foo") 81 | strCmp("foo", "foo") 82 | strCmp("foo", "foo") 83 | strCmp("foo", "foo") 84 | strCmp("foo", "foo") 85 | strCmp("foo", "foo") 86 | strCmp("foo", "foo") 87 | strCmp("foo", "foo") 88 | strCmp("foo", "foo") 89 | 90 | "these will segfault if they run strcmp" 91 | assert(strCmp(0, 0) == true) 92 | assert(strCmp(true, false) == false) 93 | -------------------------------------------------------------------------------- /test/deoptimize/strings.vvn_expectederrors: -------------------------------------------------------------------------------- 1 | Error: Got a non-string in a string operation 2 | Error: Got a non-string in a string operation 3 | Error: Got a non-string in a string operation 4 | Error: Got a non-string in a string operation 5 | Error: Got a non-string in a string operation 6 | Error: Got a non-string in a string operation 7 | Error: Got a wrong type in an operation for ints/strings/doubles 8 | Error: Got a wrong type in an operation for ints/strings/doubles 9 | Error: Got a wrong type in an operation for ints/strings/doubles 10 | Error: Got a wrong type in an operation for ints/strings/doubles 11 | Error: Got a wrong type in an operation for ints/strings/doubles 12 | -------------------------------------------------------------------------------- /test/error/interpret_type_errors.vvn: -------------------------------------------------------------------------------- 1 | 1 + true 2 | 1 + false 3 | 1 + void 4 | 1 + [] 5 | 1 + object() 6 | true + 1 7 | false + 1 8 | void + 1 9 | [] + 1 10 | object() + 1 11 | 12 | "foo" + true 13 | "foo" + false 14 | "foo" + void 15 | "foo" + [] 16 | "foo" + object() 17 | true + "foo" 18 | false + "foo" 19 | void + "foo" 20 | [] + "foo" 21 | object() + "foo" 22 | 23 | 1 + "foo" 24 | "foo" + 1 25 | 26 | 1 - true 27 | 1 - false 28 | 1 - void 29 | 1 - "foo" 30 | 1 - [] 31 | 1 - object() 32 | true - 1 33 | false - 1 34 | void - 1 35 | "foo" - 1 36 | [] - 1 37 | object() - 1 38 | 39 | 1 * true 40 | 1 * false 41 | 1 * void 42 | 1 * "foo" 43 | 1 * [] 44 | 1 * object() 45 | true * 1 46 | false * 1 47 | void * 1 48 | "foo" * 1 49 | [] * 1 50 | object() * 1 51 | 52 | 1 / true 53 | 1 / false 54 | 1 / void 55 | 1 / "foo" 56 | 1 / [] 57 | 1 / object() 58 | true / 1 59 | false / 1 60 | void / 1 61 | "foo" / 1 62 | [] / 1 63 | object() / 1 64 | 65 | 1 > true 66 | 1 > false 67 | 1 > void 68 | 1 > "foo" 69 | 1 > [] 70 | 1 > object() 71 | true > 1 72 | false > 1 73 | void > 1 74 | "foo" > 1 75 | [] > 1 76 | object() > 1 77 | 78 | 1 <= true 79 | 1 <= false 80 | 1 <= void 81 | 1 <= "foo" 82 | 1 <= [] 83 | 1 <= object() 84 | true <= 1 85 | false <= 1 86 | void <= 1 87 | "foo" <= 1 88 | [] <= 1 89 | object() <= 1 90 | 91 | 1 > true 92 | 1 > false 93 | 1 > void 94 | 1 > "foo" 95 | 1 > [] 96 | 1 > object() 97 | true > 1 98 | false > 1 99 | void > 1 100 | "foo" > 1 101 | [] > 1 102 | object() > 1 103 | 104 | 1 >= true 105 | 1 >= false 106 | 1 >= void 107 | 1 >= "foo" 108 | 1 >= [] 109 | 1 >= object() 110 | true >= 1 111 | false >= 1 112 | void >= 1 113 | "foo" >= 1 114 | [] >= 1 115 | object() >= 1 116 | 117 | 1.foo 118 | "foo".foo 119 | true.foo 120 | false.foo 121 | void.foo 122 | [].foo 123 | 124 | 1[0] 125 | "foo"[0] 126 | true[0] 127 | false[0] 128 | void[0] 129 | object()[0] 130 | 131 | []["foo"] 132 | [][true] 133 | [][false] 134 | [][void] 135 | [][object()] 136 | 137 | object()[0] 138 | object()[true] 139 | object()[false] 140 | object()[void] 141 | object()[object()] 142 | 143 | !2 144 | !"foo" 145 | ![] 146 | !void 147 | !object() 148 | 149 | if 2 do end 150 | if "foo" do end 151 | if [] do end 152 | if void do end 153 | if object() do end 154 | 155 | for 2 do end 156 | for "foo" do end 157 | for [] do end 158 | for void do end 159 | for object() do end 160 | -------------------------------------------------------------------------------- /test/interpret/doubles.vvn: -------------------------------------------------------------------------------- 1 | assert(1.2 + 3.4 == 4.6) 2 | assert(3.4 - 1.2 == 2.2) 3 | assert(3.4 * 1.2 == 4.08) 4 | assert(2.4 / 1.2 == 2.0) 5 | 6 | assert(1 + 3.4 == 4.4) 7 | assert(3 - 1.2 == 1.8) 8 | assert(3 * 1.2 == 3.5999999999999997) 9 | assert(5 / 2.5 == 2.0) 10 | 11 | assert(3.4 + 1 == 4.4) 12 | assert(3.2 - 1 == 2.2) 13 | assert(1.2 * 3 == 3.5999999999999997) 14 | assert(2.5 / 5 == 0.5) 15 | 16 | assert(3.4 > 3.3) 17 | assert(3.4 >= 3.3) 18 | assert(3.3 >= 3.3) 19 | assert(3.3 <= 3.3) 20 | assert(3.3 <= 3.4) 21 | assert(3.3 < 3.4) 22 | 23 | assert(!(3.4 < 3.3)) 24 | assert(!(3.4 <= 3.3)) 25 | assert(!(3.3 >= 3.4)) 26 | assert(!(3.3 > 3.4)) 27 | 28 | assert(4 > 3.3) 29 | assert(4 >= 3.3) 30 | assert(3 <= 3.4) 31 | assert(3 < 3.4) 32 | 33 | assert(3.4 > 3) 34 | assert(3.4 >= 3) 35 | assert(3.3 <= 4) 36 | assert(3.3 < 4) 37 | 38 | assert(!(4 < 3.3)) 39 | assert(!(4 <= 3.3)) 40 | assert(!(3 >= 3.4)) 41 | assert(!(3 > 3.4)) 42 | 43 | assert(!(3.4 < 3)) 44 | assert(!(3.4 <= 3)) 45 | assert(!(3.3 >= 4)) 46 | assert(!(3.3 > 4)) 47 | 48 | assert(3.0 >= 3) 49 | assert(3.0 == 3) 50 | assert(3.0 <= 3) 51 | 52 | assert(3 >= 3.0) 53 | assert(3 == 3.0) 54 | assert(3 <= 3.0) 55 | 56 | assert(!(3.0 < 3)) 57 | assert(!(3.0 > 3)) 58 | assert(!(3 < 3.0)) 59 | assert(!(3 > 3.0)) 60 | -------------------------------------------------------------------------------- /test/interpret/lists.vvn: -------------------------------------------------------------------------------- 1 | assert(toString([]) == "[]") 2 | assert(toString([][0]) == "void") 3 | assert(toString([][3]) == "void") 4 | 5 | assert(toString([1]) == "[1]") 6 | assert([1][0] == 1) 7 | assert(toString([1][1]) == "void") 8 | assert(toString([1][3]) == "void") 9 | 10 | assert(toString([1, 2]) == "[1, 2]") 11 | assert([1, 2][0] == 1) 12 | assert([1, 2][1] == 2) 13 | assert(toString([1, 2][2]) == "void") 14 | assert(toString([1, 2][3]) == "void") 15 | 16 | assert(toString([1, [], 2]) == "[1, [], 2]") 17 | assert([1, [], 2][0] == 1) 18 | assert(toString([1, [], 2][1]) == "[]") 19 | assert([1, [], 2][2] == 2) 20 | assert(toString([1, 2][3]) == "void") 21 | assert(toString([1, 2][5]) == "void") 22 | 23 | var list = [1, 2] 24 | assert(toString(list) == "[1, 2]") 25 | assert(list[0] == 1) 26 | assert(list[1] == 2) 27 | assert(toString([list]) == "[[1, 2]]") 28 | assert([list][0] == list); 29 | assert([list][0][0] == 1); 30 | assert([list][0][1] == 2); 31 | 32 | var i = 0 33 | var shouldBeNew = []; 34 | for i < 10 35 | shouldBeNew = [1, 2] 36 | assert(toString(shouldBeNew) == "[1, 2]") 37 | append(shouldBeNew, 3) 38 | assert(toString(shouldBeNew) == "[1, 2, 3]") 39 | i = i + 1 40 | end 41 | -------------------------------------------------------------------------------- /test/interpret/modeq.vvn: -------------------------------------------------------------------------------- 1 | var x = 1 2 | 3 | assert((x += 2) == 3) 4 | assert(x == 3) 5 | 6 | assert((x -= 1) == 2) 7 | assert(x == 2) 8 | 9 | assert((x *= 2) == 4) 10 | assert(x == 4) 11 | 12 | assert((x /= 2) == 2) 13 | assert(x == 2) 14 | 15 | x = "foo" 16 | 17 | assert((x += "bar") == "foobar") 18 | assert(x == "foobar") 19 | 20 | x = [2] 21 | 22 | var observable = [0] 23 | fn inc of observable, retval is 24 | observable[0] += 1 25 | ret retval 26 | end 27 | 28 | assert((x[inc(observable, 0)] += 3) == 5) 29 | assert(x[0] == 5) 30 | assert(observable[0] == 1) 31 | 32 | var o = object() 33 | 34 | o.foo = "foo" 35 | 36 | assert((inc(observable, o).foo += "bar") == "foobar") 37 | assert(o.foo == "foobar") 38 | assert(observable[0] == 2) 39 | -------------------------------------------------------------------------------- /test/interpret/objects.vvn: -------------------------------------------------------------------------------- 1 | var o = object(); 2 | 3 | assert(o.foo == void) 4 | assert(o.bar == void) 5 | assert(o["foo"] == void) 6 | assert(o["bar"] == void) 7 | 8 | o.foo = 4 9 | 10 | assert(o.foo == 4) 11 | assert(o.bar == void) 12 | assert(o["foo"] == 4) 13 | assert(o["bar"] == void) 14 | 15 | o.foo = 4 16 | 17 | assert(o.foo == 4) 18 | assert(o.bar == void) 19 | assert(o["foo"] == 4) 20 | assert(o["bar"] == void) 21 | 22 | assert((o.foo = "bar") == "bar") 23 | assert(o.foo == "bar") 24 | assert(o.bar == void) 25 | assert(o["foo"] == "bar") 26 | assert(o["bar"] == void) 27 | 28 | o.bar = 4 29 | 30 | assert(o.foo == "bar") 31 | assert(o.bar == 4) 32 | assert(o["foo"] == "bar") 33 | assert(o["bar"] == 4) 34 | 35 | assert((o["baz"] = "bang") == "bang") 36 | assert(o.foo == "bar") 37 | assert(o.bar == 4) 38 | assert(o.baz == "bang") 39 | assert(o["foo"] == "bar") 40 | assert(o["bar"] == 4) 41 | assert(o["baz"] == "bang") 42 | -------------------------------------------------------------------------------- /test/interpret/strings.vvn: -------------------------------------------------------------------------------- 1 | assert("foo" == "foo") 2 | assert("foo" + "bar" == "foobar") 3 | -------------------------------------------------------------------------------- /test/parser/comments_test.vvn: -------------------------------------------------------------------------------- 1 | assert(1 == 1) // comment at EOL is like a semicolon 2 | 3 | // lots of free standing comments should be OK 4 | // lots of free standing comments should be OK 5 | // lots of free standing comments should be OK 6 | // lots of free standing comments should be OK 7 | 8 | assert( // a comment mid-expression should be ok 9 | true // this too 10 | // should be OK to start a new line mid expression 11 | // and should be OK to have spaces in front 12 | ) // hopefully that worked! 13 | 14 | var x = 1 // comment 15 | assert(x == 1) 16 | 17 | var // pause! 18 | y // pause! 19 | = // pause! 20 | 4 // end of statement 21 | assert(y == 4) 22 | 23 | // should be OK with no EOL after this comment -------------------------------------------------------------------------------- /test/parser/control_flow.vvn: -------------------------------------------------------------------------------- 1 | if false 2 | end 3 | 4 | for false 5 | end 6 | 7 | if false 8 | else 9 | end 10 | 11 | if false 12 | else if false 13 | end 14 | 15 | if false 16 | else 17 | if false 18 | end 19 | end 20 | 21 | if false 22 | else 23 | for false 24 | end 25 | end 26 | 27 | if false for false 28 | end 29 | 30 | if false 31 | for false 32 | end 33 | end 34 | 35 | for false if true 36 | end 37 | 38 | for false 39 | if true 40 | end 41 | end 42 | 43 | if true if false 44 | end 45 | 46 | if true 47 | if false 48 | end 49 | end 50 | 51 | for false for false 52 | end 53 | 54 | for false 55 | for false 56 | end 57 | end 58 | -------------------------------------------------------------------------------- /test/parser/functions_test.vvn: -------------------------------------------------------------------------------- 1 | fn withis is 2 | end 3 | 4 | fn noargs 5 | end 6 | 7 | fn onelineempty is end 8 | 9 | fn onearg of x is 10 | end 11 | 12 | fn oneargonelineempty of x is end 13 | 14 | fn twoargs of x, y is 15 | end 16 | 17 | fn twoargsonelineempty of x, y is end 18 | 19 | fn multilineargs of 20 | x 21 | y 22 | is 23 | end 24 | 25 | fn multilineargscommas of 26 | x, 27 | y, 28 | is 29 | end 30 | 31 | fn trailingcomma of x, y, is 32 | end 33 | 34 | fn withexprstmt 35 | "foo" 36 | end 37 | 38 | fn withifstmt 39 | if true 40 | end 41 | end 42 | 43 | fn withforcond 44 | for true 45 | end 46 | end 47 | 48 | fn withmultiplestmts 49 | "foo" 50 | "bar" 51 | if true do end 52 | for false do end 53 | end 54 | 55 | fn onelinewithstmt is "foo"; end 56 | 57 | fn onelinewithargstmt of x is "foo"; end 58 | 59 | fn onelinewithargsstmts of x, y is "foo"; "bar"; end 60 | -------------------------------------------------------------------------------- /test/parser/fuzz_test.vvn: -------------------------------------------------------------------------------- 1 | of ==if foo (+end== ;end 3false 2z=2=(x 3 * == =,= if is ==3doisendx, is 4 z36 , , do z (;+ x 4==>/enddo=>ret ( 1( fn+ * * 7 | true 2 foox/falseof false; 5y 2 ==1 *< falseof > (>ret 2 true fordo < 5 )for ;+2 <,isfalsexretfoo ; 3ret6 *xz; )y( ret /,= 7 ;==yx retend end foo"foo" 5 offn 8 | foo of+ / 9 | x if"foo"do for "foo" *end>+ret = 1; , fndo 1/ true ifret ret "foo" 7 fn 6ofx >77x == 4is 10 | true false endret do fn"foo" true 3) * y / of7 5foo false<*fn true 3 ;37x 11 | of ; ret 4 > =3 y5> ==false 16 | 2z 4 5== 7 ret yis"foo"x === "foo" if< fn if "foo" ( fn 6 + ==is 6 if end ;= (for4 endend falsez do= x>,true /+end/ (if / "foo" z 18 | 3if 6 19 | 7/5 76;== xret== x= do6 < isfalse ofof( / ;fn 2 )for7 of) for is 20 | 2 false> * =*z 7 13) +5 > if =* ret == ) >53 21 | forx y 52ret / 6 22 | x 2 if fn+6of *7 23 | ;doif 4* 4 5 foo 24 | y false x if +false* +z 2 foo falsefooz4,fory( 6 6 7 6<+ 6 *)+= ( , 6 z of z "foo"+ end ) 5> 3 do 5 25 | ; zifof )5 is,/ z fn + fn 4+ xof) 6 false47 doendiffalse truedo5+truetrue 5 fn "foo" of +y2 * ; 26 | (if for < fn)/ z "foo"y1"foo" 1 if5 ofz/ 6 2 x isx"foo" 3 for +is+ 6 "foo"5 of>endfn ( is * ;if"foo" of 27 | false=<(is fntrue (< iffnif"foo" isfoo 2 for( if (>1 4 foo== ;false z x/2 ( ; ) == ret true z * =endifif end 1* 1 > 5 is for/ 6 is= 4 + = "foo" if y of<4 of ret)end 1+>zis "foo"5, 27 2;+ ==7< 3foo end of * is+ 1 7 fn== 7 7 forfor 28 | of (53 ==,end do z< 29 | 30 | end* 5( do "foo" "foo" 4 end true"foo"=="foo"2 3 "foo" do / 31 | < fn is "foo"/ xtrue 3 "foo" 1x true foo;false;2 foo 2end 1 5foo5 foo 6 true foo 6 )x7/* 2 "foo" ,3, for of 4 ="foo"do do3 x 7x*) xy 5if,foo +end forfoo < 1ret+x ,6falseis5is , z ret 5 end for; + yend 4 === end (false z ) ;true( )>"foo" do 6fn falseret y retz 1fn +) y*+ foois ;ret7 false( is5z 4++, ; fnfor/(3, , fn foo x + 35 | *= "foo"4 / < ( 1 ret /3endend == 3 4 is+ ==for foo truefoo 7 z 3 , retof truetrue falsey== y false+ x , 39 | ret end ="foo" "foo" of foo false y4( 4 xend 4 40 | do221; / * *==,*z+ z z /y 41 | foo fn 6 /if=/< 7ret, ( fn of for = 5"foo"2end 1 < 7end>/ 5 true1 < ** 6 7 y is of> /"foo"false == 3is7 yret if 5y / 6 >ret3x = false== is)<5 6"foo" fn1 ==for ==x 7 43 | 4 < fn)1 >foo )2isif ( endy==) 1 x 44 | 5 >* * of / for/ == if1 47 ifdo 1 z/"foo" 6 end ;( == * 45 | z; for 6 4== / ( endfalse < (false of 5 of "foo"* ofdofoo2== endif y is foo true ret false 5ret 5 )x/ >7 end yis / foo 5is; 49 | do 2 1 5 ret isfnend = 3 >false 6 of y3 do4;end 50 | 3 6/ / ( ==do47 of 6fn /2 (5 51 | for7 xfor of dofalsefalse /* = >= ) == for1)x== x ) 6==y endx< z1 4z = ==(/ (dofn z/"foo"(5"foo" 2 7 +y of >zdo31 forfalse for , 2 2 x / 3 end ) false z (foo4== >y* fn(+ 56 | /if is) /zof > + ret+ / 1y 3 z"foo" of* foo y2oftrue *( ,,) == ( ; y + do falsey7if "foo"true<3 ifof1 ==== ;end 59 | fnisfn1 end )> for ))4false if 366 / == fooend= fordo6 60 | false y * z 5 ;if <; 36y iffalse do7 ret3 xret 3of 61 | 62 | 1fn false= is 5foo of*is forfalsex y+*1,for ifisfn fn)zret> x== for > of fn 7 false 64 | 74 is( fn false3 "foo"foofn trueforfoo () ;dofor< =/ of falsefooret"foo" iffor 7fn )x 65 | xret , foo 66 | 4 fn 7 / ( =>2 fny7> , 67 | true >forend 3 foo5 ret11do7> )2) 68 | false 3 trueof ,= )( end * "foo"> false is 5 do true fn endx< 3(forend , fn+x 69 | false 6<6,2end y"foo" ; =/fn "foo" 7 * 2 ,=2 *true)42<1 2end foo==fn*4 fnend end / of false isx,3falseoffor y5 z 2 x (==if > > , /)do end for , of ;1 iffalse + + do( yretis1 / ret < fn y 2) if, 70 | forret 1 > = * fnret + 5 71 | if(ifis retfalse * 3*42) ytrue <1 true;> 6 ++ true5 z /< ;if 2; >false ) 1 <1 ,/z ret foo do3 >< ( 72 | =5 fnfalse 73 | > false 5 of21 end fn ret) "foo"fnret+ret z* fn x 4 6 + fn= foris false is do ( doend ( > ( 78 | /3 is do 79 | foo7is ("foo"x++1 > 4 false 3for for ) + )ret 5 == "foo"is ; if4 of ==endxtrue ret < if 7 <7 ret end,true 1 if ) 6 5 4do+ ; of ret;"foo" 7 "foo"( 80 | end"foo" is *(truefalse, ;x= = 81 | +==<7 if fooif 1for /foo6 xret if if > * (,; 2 true false y* ret ;z 82 | -------------------------------------------------------------------------------- /test/parser/fuzz_test_generate.js: -------------------------------------------------------------------------------- 1 | tokens = [ 2 | 'fn', 3 | 'foo', 4 | 'of', 5 | 'x', 6 | ',', 7 | 'y', 8 | ' ', 9 | 'is', 10 | '\n', 11 | '\t', 12 | 'ret', 13 | '1', 14 | '+', 15 | '2', 16 | '*', 17 | '3', 18 | '/', 19 | '4', 20 | '==', 21 | '5', 22 | '>', 23 | '6', 24 | '<', 25 | '(', 26 | 'z', 27 | '=', 28 | '7', 29 | ')', 30 | ';', 31 | 'for', 32 | 'if', 33 | 'do', 34 | '"foo"', 35 | 'true', 36 | 'false', 37 | 'end']; 38 | 39 | var out = ""; 40 | for (var x = 0; x < 5000; ++x) { 41 | var rand = Math.floor(Math.random() * tokens.length); 42 | out += tokens[rand]; 43 | x++; 44 | if (Math.random() > .5) { 45 | out += " "; 46 | } 47 | } 48 | 49 | console.log(out); 50 | -------------------------------------------------------------------------------- /test/parser/onliner.vvn: -------------------------------------------------------------------------------- 1 | if true do 'something with semi'; end 2 | if true do 'something without semi' end 3 | if true do 'multiple'; 'things'; 'semi'; end 4 | if true do 'multiple'; 'things'; 'no semi' end 5 | 6 | if true 7 | else do 'something with semi'; end 8 | if true 9 | else do 'something without semi' end 10 | if true 11 | else do 'multiple'; 'things'; 'semi'; end 12 | if true 13 | else do 'multiple'; 'things'; 'no semi' end 14 | 15 | for false do 'something with semi'; end 16 | for false do 'something without semi' end 17 | for false do 'multiple'; 'things'; 'semi'; end 18 | for false do 'multiple'; 'things'; 'no semi' end 19 | 20 | if true do 'something with semi'; else do 'something with semi'; end 21 | if true do 'something without semi' else do 'something without semi' end 22 | if true do 'multiple'; 'things'; 'semi'; else do 'multiple'; 'things'; 'semi'; end 23 | if true do 'multiple'; 'things'; 'no semi' else do 'multiple'; 'things'; 'no semi' end 24 | 25 | -------------------------------------------------------------------------------- /test/parser/recovery_test.vvn: -------------------------------------------------------------------------------- 1 | fn missingIs 6; end 2 | assert(missingIs() == 6) 3 | 4 | fn is "missing name"; end 5 | fn of x is "missing name"; end 6 | fn "missing name and is"; end 7 | 8 | var wontBeDefined = ; 9 | wontBeDefined 10 | 11 | fn ifNoDo is 12 | if true ret true end 13 | ret false 14 | end 15 | 16 | assert(ifNoDo() == true); 17 | 18 | fn forNoDo is 19 | for true ret true end 20 | ret false 21 | end 22 | 23 | assert(forNoDo() == true); 24 | 25 | fn danglingValueEvaluates 26 | ret true false 27 | end 28 | 29 | assert(danglingValueEvaluates() == true) 30 | 31 | fn danglingOpEvaluates of type is 32 | if type == "+" 33 | ret 1 + 34 | else if type == "-" 35 | ret 2 - 36 | else if type == "*" 37 | ret 3 * 38 | else if type == "/" 39 | ret 4 / 40 | else if type == "==" 41 | ret 5 == 42 | else if type == "=" 43 | ret 6 = 44 | else if type == "!=" 45 | ret 7 != 46 | else if type == "<=" 47 | ret 8 <= 48 | else if type == ">=" 49 | ret 9 >= 50 | else if type == "<" 51 | ret 10 < 52 | else if type == ">" 53 | ret 11 > 54 | end 55 | end 56 | 57 | assert(danglingOpEvaluates("+") == 1) 58 | assert(danglingOpEvaluates("-") == 2) 59 | assert(danglingOpEvaluates("*") == 3) 60 | assert(danglingOpEvaluates("/") == 4) 61 | assert(danglingOpEvaluates("==") == 5) 62 | assert(danglingOpEvaluates("=") == 6) 63 | assert(danglingOpEvaluates("!=") == 7) 64 | assert(danglingOpEvaluates("<=") == 8) 65 | assert(danglingOpEvaluates(">=") == 9) 66 | assert(danglingOpEvaluates("<") == 10) 67 | assert(danglingOpEvaluates(">") == 11) 68 | 69 | assert(4 + + 4 == 8) 70 | assert(4 + - 4 == 0) 71 | assert(4 == 4; 72 | assert((4 == 4; 73 | assert(((4 == 4; 74 | (assert(((4 == 4; 75 | assert(4 == 4)) 76 | assert(4 == 4))) 77 | 78 | ["unbalanced") 79 | ("unbalanced"] 80 | 81 | fn identity of x is x; end 82 | 83 | assert(identity(3] == 3) 84 | assert(identity(3] != 3) 85 | 86 | assert(3 == len([1, 2, 3; 87 | -------------------------------------------------------------------------------- /test/parser/recovery_test.vvn_expectederrors: -------------------------------------------------------------------------------- 1 | Parse Error: missing is at end of function at function missingIs 2 | Parse Error: missing function name at function declaration 3 | Parse Error: missing function name at function declaration 4 | Parse Error: missing is at end of function at function without a name 5 | Parse Error: missing function name at function declaration 6 | Parse Error: tried to parse a value, but got an unknown token at top level 7 | Error: Accessed a var that does not exist 8 | Parse Error: tried to parse a value, but got an unknown token at top level 9 | Parse Error: tried to parse a value, but got an unknown token at top level 10 | Parse Error: missing semicolon (or newline) at end of return at function danglingValueEvaluates 11 | Parse Error: tried to parse a value, but got an unknown token at function danglingOpEvaluates 12 | Parse Error: tried to parse a value, but got an unknown token at function danglingOpEvaluates 13 | Parse Error: tried to parse a value, but got an unknown token at function danglingOpEvaluates 14 | Parse Error: tried to parse a value, but got an unknown token at function danglingOpEvaluates 15 | Parse Error: tried to parse a value, but got an unknown token at function danglingOpEvaluates 16 | Parse Error: tried to parse a value, but got an unknown token at function danglingOpEvaluates 17 | Parse Error: tried to parse a value, but got an unknown token at function danglingOpEvaluates 18 | Parse Error: tried to parse a value, but got an unknown token at function danglingOpEvaluates 19 | Parse Error: tried to parse a value, but got an unknown token at function danglingOpEvaluates 20 | Parse Error: tried to parse a value, but got an unknown token at function danglingOpEvaluates 21 | Parse Error: tried to parse a value, but got an unknown token at function danglingOpEvaluates 22 | Parse Error: tried to parse a value, but got an unknown token at top level 23 | Parse Error: tried to parse a value, but got an unknown token at top level 24 | Parse Error: missing close paren for function call at top level 25 | Parse Error: missing close paren for subexpression at top level 26 | Parse Error: missing close paren for function call at top level 27 | Parse Error: missing close paren for subexpression at top level 28 | Parse Error: missing close paren for subexpression at top level 29 | Parse Error: missing close paren for function call at top level 30 | Parse Error: missing close paren for subexpression at top level 31 | Parse Error: missing close paren for subexpression at top level 32 | Parse Error: missing close paren for function call at top level 33 | Parse Error: missing close paren for subexpression at top level 34 | Parse Error: missing semicolon (or newline) at end of expression at top level 35 | Parse Error: expected expression, got a close paren at top level 36 | Parse Error: tried to parse a value, but got an unknown token at top level 37 | Parse Error: missing semicolon (or newline) at end of expression at top level 38 | Parse Error: expected expression, got a close paren at top level 39 | Parse Error: expected expression, got a close paren at top level 40 | Parse Error: tried to parse a value, but got an unknown token at top level 41 | Parse Error: missing close bracket for list literal at top level 42 | Parse Error: missing close paren for subexpression at top level 43 | Parse Error: missing semicolon (or newline) at end of expression at top level 44 | Parse Error: expected expression, got a close bracket at top level 45 | Parse Error: tried to parse a value, but got an unknown token at top level 46 | Parse Error: missing close paren for function call at top level 47 | Parse Error: missing close paren for function call at top level 48 | Error: assertion failed 49 | Parse Error: missing close bracket for list literal at top level 50 | Parse Error: missing close paren for function call at top level 51 | Parse Error: missing close paren for function call at top level 52 | Parse Error: missing semicolon (or newline) at end of expression at top level 53 | -------------------------------------------------------------------------------- /test/parser/strings.vvn: -------------------------------------------------------------------------------- 1 | "double quoted strings" 2 | 3 | 'single quoted strings' 4 | 5 | 'multi 6 | line 7 | string 8 | with 9 | single 10 | quotes' 11 | 12 | "multi 13 | line 14 | string 15 | with 16 | double 17 | quotes" 18 | -------------------------------------------------------------------------------- /test/parser/terms.vvn: -------------------------------------------------------------------------------- 1 | true 2 | false 3 | void 4 | -------------------------------------------------------------------------------- /test/run.sh: -------------------------------------------------------------------------------- 1 | for i in */*.vvn 2 | do 3 | echo run $i 4 | output="$(cat $i | ../vvn )" 5 | if [ $? -ne 0 ] 6 | then 7 | echo "$output" 8 | echo "nonzero exit" 9 | elif [ -e "$i""_expectederrors" ] 10 | then 11 | diff "$i""_expectederrors" <(echo "$output" | grep Error) 12 | else 13 | echo "$output" | grep Error 14 | fi 15 | echo $i done 16 | done 17 | -------------------------------------------------------------------------------- /test/std/lists_test.vvn: -------------------------------------------------------------------------------- 1 | var list = [] 2 | 3 | assert(list.len() == 0) 4 | assert(list.toString() == "[]") 5 | 6 | list[0] = true 7 | 8 | assert(list.len() == 1) 9 | assert(list.toString() == "[true]") 10 | 11 | list[0] = false 12 | 13 | assert(list.len() == 1) 14 | assert(list.toString() == "[false]") 15 | 16 | list[3] = 100 17 | 18 | assert(list.len() == 4) 19 | assert(list.toString() == "[false, void, void, 100]") 20 | 21 | list.append(500) 22 | 23 | assert(list.len() == 5) 24 | assert(list.toString() == "[false, void, void, 100, 500]") 25 | 26 | list.append() 27 | assert(list.len() == 6) 28 | assert(list.toString() == "[false, void, void, 100, 500, void]") 29 | 30 | list.append(list) 31 | assert(list.len() == 7) 32 | assert(list[6] == list) 33 | -------------------------------------------------------------------------------- /test/std/objects_test.vvn: -------------------------------------------------------------------------------- 1 | var obj = object() 2 | 3 | assert(obj != object()) 4 | 5 | assert(obj.toString() == "{}") 6 | 7 | assert(obj.keys().len() == 0) 8 | 9 | obj.foo = "bar" 10 | 11 | assert(obj.keys().len() == 1) 12 | assert(obj.keys()[0] == "foo") 13 | assert(obj.toString() == "{foo:bar}") 14 | 15 | obj.foo = "foo" 16 | 17 | assert(obj.keys().len() == 1) 18 | assert(obj.keys()[0] == "foo") 19 | assert(obj.toString() == "{foo:foo}") 20 | 21 | obj.bar = "foo" 22 | 23 | assert(obj.keys().len() == 2) 24 | assert(obj.keys()[1] == "foo") 25 | assert(obj.keys()[0] == "bar") 26 | assert(obj.toString() == "{bar:foo, foo:foo}") 27 | 28 | obj.foo = "bar" 29 | 30 | assert(obj.keys().len() == 2) 31 | assert(obj.keys()[1] == "foo") 32 | assert(obj.keys()[0] == "bar") 33 | assert(obj.toString() == "{bar:foo, foo:bar}") 34 | 35 | -------------------------------------------------------------------------------- /test/std/strings_test.vvn: -------------------------------------------------------------------------------- 1 | var foo = "foo" 2 | var bar = "bar" 3 | 4 | assert(foo.append(bar) == "foobar") 5 | 6 | assert(foo.len() == 3) 7 | assert(bar.len() == 3) 8 | assert("foobar".len() == 6) 9 | 10 | assert(foo.toString() == foo) 11 | assert("foo".toString() == "foo") 12 | assert(foo.toString() == "foo") 13 | assert("foo".toString() == foo) 14 | -------------------------------------------------------------------------------- /tokenizer.h: -------------------------------------------------------------------------------- 1 | #ifndef VAIVEN_HEADER_TOKENIZER 2 | #define VAIVEN_HEADER_TOKENIZER 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | using std::istream; 10 | using std::string; 11 | using std::vector; 12 | using std::unique_ptr; 13 | 14 | namespace vaiven { 15 | 16 | class Token; 17 | 18 | enum TokenType { 19 | TOKEN_TYPE_ID, 20 | TOKEN_TYPE_STRING, 21 | TOKEN_TYPE_FN, 22 | TOKEN_TYPE_END, 23 | TOKEN_TYPE_IS, 24 | TOKEN_TYPE_IF, 25 | TOKEN_TYPE_OF, 26 | TOKEN_TYPE_VAR, 27 | TOKEN_TYPE_RET, 28 | TOKEN_TYPE_FOR, 29 | TOKEN_TYPE_ELSE, 30 | TOKEN_TYPE_DO, 31 | TOKEN_TYPE_TRUE, 32 | TOKEN_TYPE_FALSE, 33 | TOKEN_TYPE_VOID, 34 | TOKEN_TYPE_INTEGER, 35 | TOKEN_TYPE_DOUBLE, 36 | TOKEN_TYPE_DOT, 37 | TOKEN_TYPE_PLUS, 38 | TOKEN_TYPE_MINUS, 39 | TOKEN_TYPE_DIVIDE, 40 | TOKEN_TYPE_MULTIPLY, 41 | TOKEN_TYPE_EQ, 42 | TOKEN_TYPE_EQEQ, 43 | TOKEN_TYPE_BANGEQ, 44 | TOKEN_TYPE_PLUSEQ, 45 | TOKEN_TYPE_SUBEQ, 46 | TOKEN_TYPE_MULEQ, 47 | TOKEN_TYPE_DIVEQ, 48 | TOKEN_TYPE_BANG, 49 | TOKEN_TYPE_GT, 50 | TOKEN_TYPE_GTE, 51 | TOKEN_TYPE_LT, 52 | TOKEN_TYPE_LTE, 53 | TOKEN_TYPE_OPEN_PAREN, 54 | TOKEN_TYPE_CLOSE_PAREN, 55 | TOKEN_TYPE_OPEN_BRACKET, 56 | TOKEN_TYPE_CLOSE_BRACKET, 57 | TOKEN_TYPE_OPEN_BRACE, 58 | TOKEN_TYPE_CLOSE_BRACE, 59 | TOKEN_TYPE_COMMA, 60 | TOKEN_TYPE_SEMICOLON, 61 | TOKEN_TYPE_ERROR, 62 | TOKEN_TYPE_EOF, 63 | TOKEN_TYPE_IGNORABLE_NEWLINE // this is for nextNoEol only 64 | }; 65 | 66 | class Tokenizer { 67 | public: 68 | Tokenizer(istream& stream) : input(stream) {} 69 | 70 | unique_ptr next(); 71 | unique_ptr nextNoEol(); 72 | unique_ptr nextOr(TokenType newlineType); 73 | private: 74 | unique_ptr tokenizeIsOrIf(); 75 | unique_ptr tokenizeEndOrElse(); 76 | unique_ptr tokenizeRet(); 77 | unique_ptr tokenizeDo(); 78 | unique_ptr tokenizeFnOrFalseOrFor(); 79 | unique_ptr tokenizeTrue(); 80 | unique_ptr tokenizeOf(); 81 | unique_ptr tokenizeVarOrVoid(); 82 | unique_ptr tokenizeId(vector& buffer); 83 | istream& input; 84 | 85 | }; 86 | 87 | class Token { 88 | public: 89 | Token(TokenType type) : type(type) {} 90 | TokenType type; 91 | virtual ~Token() {}; 92 | virtual Token* copy(); 93 | }; 94 | 95 | class StringToken : public Token { 96 | public: 97 | StringToken(TokenType type, string lexeme) : lexeme(lexeme), Token(type) {} 98 | TokenType type; 99 | string lexeme; 100 | virtual ~StringToken() {}; 101 | StringToken* copy(); 102 | }; 103 | 104 | class IntegerToken : public Token { 105 | public: 106 | IntegerToken(TokenType type, int value) : value(value), Token(type) {} 107 | TokenType type; 108 | int value; 109 | virtual ~IntegerToken() {}; 110 | IntegerToken* copy(); 111 | }; 112 | 113 | class DoubleToken : public Token { 114 | public: 115 | DoubleToken(TokenType type, double value) : value(value), Token(type) {} 116 | TokenType type; 117 | double value; 118 | virtual ~DoubleToken() {}; 119 | DoubleToken* copy(); 120 | }; 121 | 122 | } 123 | 124 | #endif 125 | -------------------------------------------------------------------------------- /type_info.h: -------------------------------------------------------------------------------- 1 | #ifndef VAIVEN_VISITOR_HEADER_TYPE_INFO 2 | #define VAIVEN_VISITOR_HEADER_TYPE_INFO 3 | 4 | #include "asmjit/src/asmjit/asmjit.h" 5 | 6 | namespace vaiven { 7 | 8 | enum VaivenStaticType { 9 | VAIVEN_STATIC_TYPE_VOID, 10 | VAIVEN_STATIC_TYPE_INT, 11 | VAIVEN_STATIC_TYPE_BOOL, 12 | VAIVEN_STATIC_TYPE_DOUBLE, 13 | VAIVEN_STATIC_TYPE_STRING, 14 | VAIVEN_STATIC_TYPE_OBJECT, 15 | VAIVEN_STATIC_TYPE_LIST, 16 | VAIVEN_STATIC_TYPE_UNKNOWN, 17 | }; 18 | 19 | } 20 | 21 | #endif 22 | -------------------------------------------------------------------------------- /ui_runtime/app.cpp: -------------------------------------------------------------------------------- 1 | #include "matrix.h" 2 | 3 | #include "stdio.h" 4 | 5 | using namespace vaiven; 6 | 7 | int main() { 8 | Matrix mainWindow(10, 3); 9 | mainWindow.printMany(fromStr("Hello world!")); 10 | mainWindow.move(0, 2); 11 | StyledChar a('a'); 12 | StyledChar b('b'); 13 | mainWindow.print(a); 14 | mainWindow.write(a); 15 | mainWindow.print(b); 16 | mainWindow.writeMany(fromStr("Hello world again!")); 17 | mainWindow.printMany(fromStr("overwrite all but")); 18 | mainWindow.cursor += 5; 19 | mainWindow.writeMany(fromStr("Goodbye world!")); 20 | 21 | for(int i = 0; i < mainWindow.cols * mainWindow.rows; ++i) { 22 | putchar(mainWindow.data[i].theChar); 23 | if (i % mainWindow.cols == mainWindow.cols - 1) { 24 | putchar('\n'); 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /ui_runtime/matrix.cpp: -------------------------------------------------------------------------------- 1 | #include "matrix.h" 2 | 3 | namespace vaiven { 4 | 5 | void Matrix::move(int col, int row) { 6 | cursor = row * cols + col; 7 | } 8 | 9 | StyledChar& Matrix::get(int col, int row) { 10 | return data[row * cols + col]; 11 | } 12 | 13 | vector Matrix::getMany(int col, int row, int count) { 14 | vector result(count); 15 | for(int i = 0; i < count; ++i) { 16 | result[i] = data[row * cols + col + i]; 17 | } 18 | return result; 19 | } 20 | 21 | void Matrix::write(StyledChar& theChar) { 22 | if (cursor >= cols * rows) { 23 | return; 24 | } 25 | data[cursor] = theChar; 26 | } 27 | 28 | void Matrix::print(StyledChar& theChar) { 29 | if (cursor >= cols * rows) { 30 | return; 31 | } 32 | data[cursor++] = theChar; 33 | } 34 | 35 | void Matrix::writeMany(vector theChars) { 36 | for(int i = 0; i < theChars.size(); ++i) { 37 | if (cursor + i >= cols * rows) { 38 | return; 39 | } 40 | data[cursor + i] = theChars[i]; 41 | } 42 | } 43 | 44 | void Matrix::printMany(vector theChars) { 45 | for(vector::iterator it = theChars.begin(); it != theChars.end(); ++it) { 46 | if (cursor >= cols * rows) { 47 | return; 48 | } 49 | data[cursor++] = *it; 50 | } 51 | } 52 | 53 | void Matrix::put(StyledChar& theChar, int col, int row) { 54 | if (col > cols || row > rows) { 55 | return; 56 | } 57 | data[row * cols + col] = theChar; 58 | } 59 | 60 | void Matrix::putMany(vector theChars, int col, int row) { 61 | if (row > rows) { 62 | return; 63 | } 64 | 65 | for(int i = 0; i < theChars.size(); ++i) { 66 | if (col + i > cols) { 67 | return; 68 | } 69 | 70 | data[row * cols + col + i] = theChars[i]; 71 | } 72 | } 73 | 74 | } 75 | -------------------------------------------------------------------------------- /ui_runtime/matrix.h: -------------------------------------------------------------------------------- 1 | #ifndef ENCASE_HEADER_MATRIX 2 | #define ENCASE_HEADER_MATRIX 3 | 4 | #include 5 | #include "styled_char.h" 6 | 7 | namespace vaiven { 8 | 9 | using namespace std; 10 | 11 | class Matrix { 12 | public: 13 | int cols; 14 | int rows; 15 | 16 | Matrix(int cols, int rows) : cols(cols), rows(rows), cursor(0), data(cols * rows) { 17 | } 18 | 19 | int cursor; 20 | 21 | vector data; 22 | 23 | void move(int col, int row); 24 | StyledChar& get(int col, int row); 25 | vector getMany(int col, int row, int count); 26 | void write(StyledChar& theChar); 27 | void print(StyledChar& theChar); 28 | void writeMany(vector theChars); 29 | void printMany(vector theChars); 30 | void writeManyDown(vector theChars); 31 | void printManyDown(vector theChars); 32 | void writeManyUp(vector theChars); 33 | void printManyUp(vector theChars); 34 | void writeManyLeft(vector theChars); 35 | void printManyLeft(vector theChars); 36 | void put(StyledChar& theChar, int col, int row); 37 | void putMany(vector theChars, int col, int row); 38 | }; 39 | 40 | } 41 | 42 | #endif 43 | -------------------------------------------------------------------------------- /ui_runtime/styled_char.cpp: -------------------------------------------------------------------------------- 1 | #include "styled_char.h" 2 | 3 | namespace vaiven { 4 | 5 | vector fromStr(const string& s) { 6 | vector result(s.size()); 7 | for(int i = 0; i < s.size(); ++i) { 8 | result.at(i) = StyledChar(s[i]); 9 | } 10 | 11 | return result; 12 | } 13 | 14 | } 15 | -------------------------------------------------------------------------------- /ui_runtime/styled_char.h: -------------------------------------------------------------------------------- 1 | #ifndef ENCASE_HEADER_STYLED_CHAR 2 | #define ENCASE_HEADER_STYLED_CHAR 3 | 4 | #include 5 | #include 6 | 7 | using namespace std; 8 | 9 | namespace vaiven { 10 | 11 | // TODO use less memory 12 | class StyledChar { 13 | public: 14 | // TODO support utf-8 15 | char theChar; 16 | // TODO use less memory 17 | bool isBold; 18 | bool isUnderlined; 19 | bool isItalic; 20 | int colorCode; 21 | 22 | StyledChar(char theChar) : 23 | theChar(theChar), isBold(false), isUnderlined(false), 24 | isItalic(false), colorCode(0) {}; 25 | 26 | StyledChar() : 27 | theChar(' '), isBold(false), isUnderlined(false), 28 | isItalic(false), colorCode(0) {}; 29 | }; 30 | 31 | vector fromStr(const string& s); 32 | 33 | } 34 | 35 | #endif 36 | -------------------------------------------------------------------------------- /util.h: -------------------------------------------------------------------------------- 1 | #ifndef VAIVEN_VISITOR_HEADER_UTIL 2 | #define VAIVEN_VISITOR_HEADER_UTIL 3 | 4 | #include 5 | 6 | template 7 | class stack_with_container : public std::stack { 8 | public: 9 | using std::stack::c; // expose the container 10 | }; 11 | 12 | #endif 13 | -------------------------------------------------------------------------------- /value.cpp: -------------------------------------------------------------------------------- 1 | #include "value.h" 2 | #include "heap.h" 3 | 4 | using namespace vaiven; 5 | 6 | VaivenStaticType Value::getStaticType() const { 7 | return isInt() 8 | ? VAIVEN_STATIC_TYPE_INT 9 | : isBool() 10 | ? VAIVEN_STATIC_TYPE_BOOL 11 | : isVoid() 12 | ? VAIVEN_STATIC_TYPE_VOID 13 | : isDouble() 14 | ? VAIVEN_STATIC_TYPE_DOUBLE 15 | : getPtr()->getType() == GCABLE_TYPE_STRING 16 | ? VAIVEN_STATIC_TYPE_STRING 17 | : getPtr()->getType() == GCABLE_TYPE_LIST 18 | ? VAIVEN_STATIC_TYPE_LIST 19 | : VAIVEN_STATIC_TYPE_OBJECT; 20 | } 21 | -------------------------------------------------------------------------------- /value.h: -------------------------------------------------------------------------------- 1 | #ifndef VAIVEN_VISITOR_HEADER_VALUE 2 | #define VAIVEN_VISITOR_HEADER_VALUE 3 | 4 | #include "inttypes.h" 5 | #include "type_info.h" 6 | 7 | namespace vaiven { 8 | 9 | // the largest double is nan 10 | // 11111111 11111000 00000000 00000000 00000000 00000000 00000000 00000000 11 | // largest ptr is <= 0x00007FFFFFFFFFFF 12 | // 00000000 00000000 01111111 11111111 11111111 11111111 11111111 11111111 13 | // if we flip NaN, we can say all doubles are >= 0x0007FFFFFFFFFFFF 14 | // 00000000 00000111 11111111 11111111 11111111 11111111 11111111 11111111 15 | // that means we can distinguish some magical values 16 | // 00000000 00000000 10000000 00000000 00000000 00000000 00000000 00000001 true 17 | // 00000000 00000000 10000000 00000000 00000000 00000000 00000000 00000000 false 18 | // 00000000 00000001 00000000 00000000 00000000 00000000 00000000 00000010 void 19 | // 00000000 00000010 00000000 00000000 ........ ........ ........ ........ 32 bit int 20 | 21 | const uint64_t MAX_PTR = 0x00007FFFFFFFFFFF; 22 | const uint64_t MIN_DBL = 0x0007FFFFFFFFFFFF; 23 | const uint64_t FALSE = 0x0000800000000000; 24 | const uint64_t TRUE = 0x0000800000000001; 25 | const uint64_t VOID = 0x0002000000000000; 26 | const uint64_t INT_TAG = 0x0001000000000000; 27 | const uint64_t BOOL_TAG = 0x0000800000000000; 28 | const uint64_t VALUE_TAG_SHIFT = 32; 29 | const uint64_t INT_TAG_SHIFTED = 0x00010000; 30 | const uint64_t BOOL_TAG_SHIFTED = 0x00008000; 31 | 32 | struct ValueAfterHeader { 33 | int32_t asInt; 34 | uint32_t header; 35 | }; 36 | 37 | class Gcable; 38 | 39 | class Value { 40 | private: 41 | 42 | union { 43 | Gcable* asPtr; 44 | double asDouble; 45 | uint64_t raw; 46 | ValueAfterHeader withHeader; 47 | } internals; 48 | 49 | public: 50 | 51 | inline Value(int32_t fromInt) { 52 | internals.withHeader.header = INT_TAG_SHIFTED; 53 | internals.withHeader.asInt = fromInt; 54 | } 55 | 56 | inline Value(bool fromBool) { 57 | internals.raw = fromBool ? TRUE : FALSE; 58 | } 59 | 60 | inline Value(Gcable* fromPtr) { 61 | internals.asPtr = fromPtr; 62 | } 63 | 64 | inline Value(double fromDouble) { 65 | internals.asDouble = fromDouble; 66 | internals.raw = ~internals.raw; 67 | } 68 | 69 | inline Value() { 70 | internals.raw = VOID; 71 | } 72 | 73 | inline bool isInt() const { 74 | return internals.raw >> VALUE_TAG_SHIFT == INT_TAG_SHIFTED; 75 | } 76 | 77 | inline bool isPtr() const { 78 | return internals.raw <= MAX_PTR; 79 | } 80 | 81 | inline bool isDouble() const { 82 | return internals.raw >= MIN_DBL; 83 | } 84 | 85 | inline bool isBool() const { 86 | return internals.raw >> VALUE_TAG_SHIFT == BOOL_TAG_SHIFTED; 87 | } 88 | 89 | inline bool isTrue() const { 90 | return internals.raw == TRUE; 91 | } 92 | 93 | inline bool isFalse() const { 94 | return internals.raw == FALSE; 95 | } 96 | 97 | inline bool isVoid() const { 98 | return internals.raw == VOID; 99 | } 100 | 101 | inline int32_t getInt() const { 102 | return internals.withHeader.asInt; 103 | } 104 | 105 | inline Gcable* getPtr() const { 106 | return internals.asPtr; 107 | } 108 | 109 | inline double getDouble() const { 110 | Value val = *this; 111 | val.internals.raw = ~val.internals.raw; 112 | return val.internals.asDouble; 113 | } 114 | 115 | inline bool getBool() const { 116 | return internals.withHeader.asInt; 117 | } 118 | 119 | inline uint64_t getRaw() const { 120 | return internals.raw; 121 | } 122 | 123 | VaivenStaticType getStaticType() const; 124 | }; 125 | 126 | } 127 | 128 | #endif 129 | -------------------------------------------------------------------------------- /visitor/assignment_producer.cpp: -------------------------------------------------------------------------------- 1 | #include "assignment_producer.h" 2 | 3 | #include 4 | 5 | #include "../ast/all.h" 6 | 7 | using std::cout; 8 | 9 | using namespace vaiven::visitor; 10 | 11 | void AssignmentProducer::visitIfStatement(IfStatement<>& stmt) { 12 | } 13 | 14 | void AssignmentProducer::visitForCondition(ForCondition<>& stmt) { 15 | } 16 | 17 | void AssignmentProducer::visitReturnStatement(ReturnStatement<>& stmt) { 18 | } 19 | 20 | void AssignmentProducer::visitVarDecl(VarDecl<>& varDecl) { 21 | } 22 | 23 | void AssignmentProducer::visitListLiteralExpression(ListLiteralExpression<>& expr) { 24 | } 25 | 26 | void AssignmentProducer::visitDynamicAccessExpression(DynamicAccessExpression<>& expr) { 27 | result.reset(new DynamicStoreExpression<>( 28 | std::move(expr.subject), 29 | std::move(expr.property), 30 | std::move(rhs), 31 | preAssignmentOp)); 32 | } 33 | 34 | void AssignmentProducer::visitDynamicStoreExpression(DynamicStoreExpression<>& expr) { 35 | } 36 | 37 | void AssignmentProducer::visitStaticAccessExpression(StaticAccessExpression<>& expr) { 38 | result.reset(new StaticStoreExpression<>( 39 | std::move(expr.subject), 40 | expr.property, 41 | std::move(rhs), 42 | preAssignmentOp)); 43 | } 44 | 45 | void AssignmentProducer::visitStaticStoreExpression(StaticStoreExpression<>& expr) { 46 | } 47 | 48 | void AssignmentProducer::visitFuncCallExpression(FuncCallExpression<>& expr) { 49 | } 50 | 51 | void AssignmentProducer::visitFuncDecl(FuncDecl<>& decl) { 52 | } 53 | 54 | void AssignmentProducer::visitExpressionStatement(ExpressionStatement<>& stmt) { 55 | } 56 | 57 | void AssignmentProducer::visitBlock(Block<>& block) { 58 | } 59 | 60 | void AssignmentProducer::visitAssignmentExpression(AssignmentExpression<>& expr) { 61 | } 62 | 63 | void AssignmentProducer::visitAdditionExpression(AdditionExpression<>& expr) { 64 | } 65 | 66 | void AssignmentProducer::visitSubtractionExpression(SubtractionExpression<>& expr) { 67 | } 68 | 69 | void AssignmentProducer::visitMultiplicationExpression(MultiplicationExpression<>& expr) { 70 | } 71 | 72 | void AssignmentProducer::visitDivisionExpression(DivisionExpression<>& expr) { 73 | } 74 | 75 | void AssignmentProducer::visitIntegerExpression(IntegerExpression<>& expr) { 76 | } 77 | 78 | void AssignmentProducer::visitDoubleExpression(DoubleExpression<>& expr) { 79 | } 80 | 81 | void AssignmentProducer::visitStringExpression(StringExpression<>& expr) { 82 | } 83 | 84 | void AssignmentProducer::visitVariableExpression(VariableExpression<>& expr) { 85 | result.reset(new AssignmentExpression<>(expr.id, std::move(rhs), preAssignmentOp)); 86 | } 87 | 88 | void AssignmentProducer::visitBoolLiteral(BoolLiteral<>& expr) { 89 | } 90 | 91 | void AssignmentProducer::visitVoidLiteral(VoidLiteral<>& expr) { 92 | } 93 | 94 | void AssignmentProducer::visitNotExpression(NotExpression<>& expr) { 95 | } 96 | 97 | void AssignmentProducer::visitInequalityExpression(InequalityExpression<>& expr) { 98 | } 99 | 100 | void AssignmentProducer::visitEqualityExpression(EqualityExpression<>& expr) { 101 | } 102 | 103 | void AssignmentProducer::visitGtExpression(GtExpression<>& expr) { 104 | } 105 | 106 | void AssignmentProducer::visitGteExpression(GteExpression<>& expr) { 107 | } 108 | 109 | void AssignmentProducer::visitLtExpression(LtExpression<>& expr) { 110 | } 111 | 112 | void AssignmentProducer::visitLteExpression(LteExpression<>& expr) { 113 | } 114 | -------------------------------------------------------------------------------- /visitor/assignment_producer.h: -------------------------------------------------------------------------------- 1 | #ifndef VAIVEN_VISITOR_HEADER_ASSIGNMENT_PRODUCER 2 | #define VAIVEN_VISITOR_HEADER_ASSIGNMENT_PRODUCER 3 | 4 | #include "../ast/visitor.h" 5 | #include "../ast/all.h" 6 | 7 | #include 8 | 9 | namespace vaiven { namespace visitor { 10 | 11 | using namespace vaiven::ast; 12 | using std::unique_ptr; 13 | 14 | class AssignmentProducer : public Visitor<> { 15 | 16 | public: 17 | AssignmentProducer(unique_ptr> rhs, ast::PreAssignmentOp preAssignmentOp) 18 | : rhs(std::move(rhs)), preAssignmentOp(preAssignmentOp) {}; 19 | 20 | virtual void visitAssignmentExpression(AssignmentExpression<>& expr); 21 | virtual void visitAdditionExpression(AdditionExpression<>& expr); 22 | virtual void visitSubtractionExpression(SubtractionExpression<>& expr); 23 | virtual void visitMultiplicationExpression(MultiplicationExpression<>& expr); 24 | virtual void visitDivisionExpression(DivisionExpression<>& expr); 25 | virtual void visitIntegerExpression(IntegerExpression<>& expr); 26 | virtual void visitDoubleExpression(DoubleExpression<>& expr); 27 | virtual void visitStringExpression(StringExpression<>& expr); 28 | virtual void visitVariableExpression(VariableExpression<>& expr); 29 | virtual void visitBoolLiteral(BoolLiteral<>& expr); 30 | virtual void visitVoidLiteral(VoidLiteral<>& expr); 31 | virtual void visitNotExpression(NotExpression<>& expr); 32 | virtual void visitEqualityExpression(EqualityExpression<>& expr); 33 | virtual void visitInequalityExpression(InequalityExpression<>& expr); 34 | virtual void visitGtExpression(GtExpression<>& expr); 35 | virtual void visitGteExpression(GteExpression<>& expr); 36 | virtual void visitLtExpression(LtExpression<>& expr); 37 | virtual void visitLteExpression(LteExpression<>& expr); 38 | virtual void visitFuncCallExpression(FuncCallExpression<>& expr); 39 | virtual void visitListLiteralExpression(ListLiteralExpression<>& expr); 40 | virtual void visitDynamicAccessExpression(DynamicAccessExpression<>& expr); 41 | virtual void visitDynamicStoreExpression(DynamicStoreExpression<>& expr); 42 | virtual void visitStaticAccessExpression(StaticAccessExpression<>& expr); 43 | virtual void visitStaticStoreExpression(StaticStoreExpression<>& expr); 44 | virtual void visitExpressionStatement(ExpressionStatement<>& stmt); 45 | virtual void visitIfStatement(IfStatement<>& stmt); 46 | virtual void visitForCondition(ForCondition<>& stmt); 47 | virtual void visitReturnStatement(ReturnStatement<>& stmt); 48 | virtual void visitBlock(Block<>& expr); 49 | virtual void visitFuncDecl(FuncDecl<>& funcDecl); 50 | virtual void visitVarDecl(VarDecl<>& varDecl); 51 | 52 | ast::PreAssignmentOp preAssignmentOp; 53 | unique_ptr> rhs; 54 | unique_ptr> result; 55 | 56 | }; 57 | 58 | }} 59 | 60 | #endif 61 | -------------------------------------------------------------------------------- /visitor/interpreter.h: -------------------------------------------------------------------------------- 1 | #ifndef VAIVEN_VISITOR_HEADER_INTERPRETER 2 | #define VAIVEN_VISITOR_HEADER_INTERPRETER 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include "../ast/visitor.h" 10 | #include "../ast/all.h" 11 | #include "../functions.h" 12 | #include "../value.h" 13 | #include "../scope.h" 14 | #include "../util.h" 15 | #include "../heap.h" 16 | 17 | namespace vaiven { namespace visitor { 18 | 19 | using std::map; 20 | using std::stack; 21 | using std::string; 22 | using std::vector; 23 | 24 | using namespace vaiven::ast; 25 | 26 | class Interpreter : public Visitor<> { 27 | 28 | public: 29 | Interpreter(Functions& funcs) : funcs(funcs), heap(stack, scope) { 30 | globalHeap = &heap; 31 | }; 32 | ~Interpreter() { 33 | globalHeap = NULL; 34 | } 35 | //int interpret(Node<>& root, vector args, map* variablesMap); 36 | Value interpret(Node<>& root); 37 | 38 | virtual void visitAssignmentExpression(AssignmentExpression<>& expr); 39 | virtual void visitAdditionExpression(AdditionExpression<>& expr); 40 | virtual void visitSubtractionExpression(SubtractionExpression<>& expr); 41 | virtual void visitMultiplicationExpression(MultiplicationExpression<>& expr); 42 | virtual void visitDivisionExpression(DivisionExpression<>& expr); 43 | virtual void visitIntegerExpression(IntegerExpression<>& expr); 44 | virtual void visitDoubleExpression(DoubleExpression<>& expr); 45 | virtual void visitStringExpression(StringExpression<>& expr); 46 | virtual void visitVariableExpression(VariableExpression<>& expr); 47 | virtual void visitBoolLiteral(BoolLiteral<>& expr); 48 | virtual void visitVoidLiteral(VoidLiteral<>& expr); 49 | virtual void visitNotExpression(NotExpression<>& expr); 50 | virtual void visitEqualityExpression(EqualityExpression<>& expr); 51 | virtual void visitInequalityExpression(InequalityExpression<>& expr); 52 | virtual void visitGtExpression(GtExpression<>& expr); 53 | virtual void visitGteExpression(GteExpression<>& expr); 54 | virtual void visitLtExpression(LtExpression<>& expr); 55 | virtual void visitLteExpression(LteExpression<>& expr); 56 | virtual void visitFuncCallExpression(FuncCallExpression<>& expr); 57 | virtual void visitListLiteralExpression(ListLiteralExpression<>& expr); 58 | virtual void visitDynamicAccessExpression(DynamicAccessExpression<>& expr); 59 | virtual void visitDynamicStoreExpression(DynamicStoreExpression<>& expr); 60 | virtual void visitStaticAccessExpression(StaticAccessExpression<>& expr); 61 | virtual void visitStaticStoreExpression(StaticStoreExpression<>& expr); 62 | virtual void visitExpressionStatement(ExpressionStatement<>& stmt); 63 | virtual void visitIfStatement(IfStatement<>& stmt); 64 | virtual void visitForCondition(ForCondition<>& stmt); 65 | virtual void visitReturnStatement(ReturnStatement<>& stmt); 66 | virtual void visitBlock(Block<>& expr); 67 | virtual void visitFuncDecl(FuncDecl<>& funcDecl); 68 | virtual void visitVarDecl(VarDecl<>& varDecl); 69 | 70 | stack_with_container stack; 71 | Functions& funcs; 72 | Scope scope; 73 | Heap heap; 74 | }; 75 | 76 | }} 77 | 78 | #endif 79 | -------------------------------------------------------------------------------- /visitor/print_visitor.cpp: -------------------------------------------------------------------------------- 1 | #include "print_visitor.h" 2 | 3 | #include 4 | 5 | #include "../ast/all.h" 6 | 7 | using std::cout; 8 | 9 | using namespace vaiven::visitor; 10 | 11 | void PrintVisitor::visitIfStatement(IfStatement<>& stmt) { 12 | cout << "if "; 13 | stmt.condition->accept(*this); 14 | cout << std::endl; 15 | 16 | for(vector > >::iterator it = stmt.trueStatements.begin(); 17 | it != stmt.trueStatements.end(); 18 | ++it) { 19 | (*it)->accept(*this); 20 | } 21 | 22 | cout << " else " << std::endl; 23 | 24 | for(vector > >::iterator it = stmt.falseStatements.begin(); 25 | it != stmt.falseStatements.end(); 26 | ++it) { 27 | (*it)->accept(*this); 28 | } 29 | 30 | cout << "end" << std::endl; 31 | } 32 | 33 | void PrintVisitor::visitForCondition(ForCondition<>& stmt) { 34 | cout << "for "; 35 | stmt.condition->accept(*this); 36 | cout << std::endl; 37 | cout << "do " << std::endl; 38 | 39 | for(vector > >::iterator it = stmt.statements.begin(); 40 | it != stmt.statements.end(); 41 | ++it) { 42 | (*it)->accept(*this); 43 | } 44 | 45 | cout << "end " << std::endl; 46 | } 47 | 48 | void PrintVisitor::visitReturnStatement(ReturnStatement<>& stmt) { 49 | cout << "return "; 50 | stmt.expr->accept(*this); 51 | cout << ";" << std::endl; 52 | } 53 | 54 | void PrintVisitor::visitVarDecl(VarDecl<>& varDecl) { 55 | cout << "var " << varDecl.varname << " = "; 56 | varDecl.expr->accept(*this); 57 | cout << ";" << std::endl; 58 | } 59 | 60 | void PrintVisitor::visitFuncCallExpression(FuncCallExpression<>& expr) { 61 | cout << expr.name << "("; 62 | for(vector > >::iterator it = expr.parameters.begin(); 63 | it != expr.parameters.end(); 64 | ++it) { 65 | (*it)->accept(*this); 66 | cout << ", "; 67 | } 68 | cout << ")"; 69 | } 70 | 71 | void PrintVisitor::visitListLiteralExpression(ListLiteralExpression<>& expr) { 72 | cout << "["; 73 | for(vector > >::iterator it = expr.items.begin(); 74 | it != expr.items.end(); 75 | ++it) { 76 | (*it)->accept(*this); 77 | cout << ", "; 78 | } 79 | cout << "]"; 80 | } 81 | 82 | void PrintVisitor::visitDynamicAccessExpression(DynamicAccessExpression<>& expr) { 83 | expr.subject->accept(*this); 84 | cout << "["; 85 | expr.property->accept(*this); 86 | cout << "]"; 87 | } 88 | 89 | void PrintVisitor::visitDynamicStoreExpression(DynamicStoreExpression<>& expr) { 90 | expr.subject->accept(*this); 91 | cout << "["; 92 | expr.property->accept(*this); 93 | cout << "] = "; 94 | expr.rhs->accept(*this); 95 | } 96 | 97 | void PrintVisitor::visitStaticAccessExpression(StaticAccessExpression<>& expr) { 98 | expr.subject->accept(*this); 99 | cout << "." << expr.property; 100 | } 101 | 102 | void PrintVisitor::visitStaticStoreExpression(StaticStoreExpression<>& expr) { 103 | expr.subject->accept(*this); 104 | cout << "." << expr.property << " = "; 105 | expr.rhs->accept(*this); 106 | } 107 | 108 | void PrintVisitor::visitFuncDecl(FuncDecl<>& decl) { 109 | cout << "fn " << decl.name << " of "; 110 | for (vector::iterator it = decl.args.begin(); 111 | it != decl.args.end(); 112 | ++it) { 113 | cout << *it << ", "; 114 | } 115 | cout << "is" << std::endl; 116 | for(vector > >::iterator it = decl.statements.begin(); 117 | it != decl.statements.end(); 118 | ++it) { 119 | (*it)->accept(*this); 120 | } 121 | cout << std::endl << "end" << std::endl; 122 | } 123 | 124 | void PrintVisitor::visitExpressionStatement(ExpressionStatement<>& stmt) { 125 | stmt.expr->accept(*this); 126 | cout << ";" << std::endl; 127 | } 128 | 129 | void PrintVisitor::visitBlock(Block<>& block) { 130 | cout << "{" << std::endl; 131 | for(vector > >::iterator it = block.statements.begin(); 132 | it != block.statements.end(); 133 | ++it) { 134 | (*it)->accept(*this); 135 | } 136 | cout << "}" << std::endl; 137 | } 138 | 139 | void PrintVisitor::visitAssignmentExpression(AssignmentExpression<>& expr) { 140 | cout << expr.varname << " = "; 141 | expr.expr->accept(*this); 142 | } 143 | 144 | void PrintVisitor::visitAdditionExpression(AdditionExpression<>& expr) { 145 | cout << "("; 146 | expr.left->accept(*this); 147 | cout << "+"; 148 | expr.right->accept(*this); 149 | cout << ")"; 150 | } 151 | void PrintVisitor::visitSubtractionExpression(SubtractionExpression<>& expr) { 152 | cout << "("; 153 | expr.left->accept(*this); 154 | cout << "-"; 155 | expr.right->accept(*this); 156 | cout << ")"; 157 | } 158 | void PrintVisitor::visitMultiplicationExpression(MultiplicationExpression<>& expr) { 159 | cout << "("; 160 | expr.left->accept(*this); 161 | cout << "*"; 162 | expr.right->accept(*this); 163 | cout << ")"; 164 | } 165 | void PrintVisitor::visitDivisionExpression(DivisionExpression<>& expr) { 166 | cout << "("; 167 | expr.left->accept(*this); 168 | cout << "/"; 169 | expr.right->accept(*this); 170 | cout << ")"; 171 | } 172 | 173 | void PrintVisitor::visitIntegerExpression(IntegerExpression<>& expr) { 174 | cout << expr.value; 175 | } 176 | 177 | void PrintVisitor::visitDoubleExpression(DoubleExpression<>& expr) { 178 | cout << expr.value; 179 | } 180 | 181 | void PrintVisitor::visitStringExpression(StringExpression<>& expr) { 182 | cout << expr.value->str; 183 | } 184 | 185 | void PrintVisitor::visitVariableExpression(VariableExpression<>& expr) { 186 | cout << expr.id; 187 | } 188 | 189 | void PrintVisitor::visitBoolLiteral(BoolLiteral<>& expr) { 190 | cout << expr.value; 191 | } 192 | 193 | void PrintVisitor::visitVoidLiteral(VoidLiteral<>& expr) { 194 | cout << "void"; 195 | } 196 | 197 | void PrintVisitor::visitNotExpression(NotExpression<>& expr) { 198 | cout << "!"; 199 | expr.expr->accept(*this); 200 | } 201 | 202 | void PrintVisitor::visitInequalityExpression(InequalityExpression<>& expr) { 203 | cout << "("; 204 | expr.left->accept(*this); 205 | cout << "!="; 206 | expr.right->accept(*this); 207 | cout << ")"; 208 | } 209 | 210 | void PrintVisitor::visitEqualityExpression(EqualityExpression<>& expr) { 211 | cout << "("; 212 | expr.left->accept(*this); 213 | cout << "=="; 214 | expr.right->accept(*this); 215 | cout << ")"; 216 | } 217 | 218 | void PrintVisitor::visitGtExpression(GtExpression<>& expr) { 219 | cout << "("; 220 | expr.left->accept(*this); 221 | cout << ">"; 222 | expr.right->accept(*this); 223 | cout << ")"; 224 | } 225 | 226 | void PrintVisitor::visitGteExpression(GteExpression<>& expr) { 227 | cout << "("; 228 | expr.left->accept(*this); 229 | cout << ">="; 230 | expr.right->accept(*this); 231 | cout << ")"; 232 | } 233 | 234 | void PrintVisitor::visitLtExpression(LtExpression<>& expr) { 235 | cout << "("; 236 | expr.left->accept(*this); 237 | cout << "<"; 238 | expr.right->accept(*this); 239 | cout << ")"; 240 | } 241 | 242 | void PrintVisitor::visitLteExpression(LteExpression<>& expr) { 243 | cout << "("; 244 | expr.left->accept(*this); 245 | cout << "<="; 246 | expr.right->accept(*this); 247 | cout << ")"; 248 | } 249 | -------------------------------------------------------------------------------- /visitor/print_visitor.h: -------------------------------------------------------------------------------- 1 | #ifndef VAIVEN_VISITOR_HEADER_PRINT_VISITOR 2 | #define VAIVEN_VISITOR_HEADER_PRINT_VISITOR 3 | 4 | #include "../ast/visitor.h" 5 | 6 | namespace vaiven { namespace visitor { 7 | 8 | using namespace vaiven::ast; 9 | 10 | class PrintVisitor : public Visitor<> { 11 | 12 | public: 13 | virtual void visitAssignmentExpression(AssignmentExpression<>& expr); 14 | virtual void visitAdditionExpression(AdditionExpression<>& expr); 15 | virtual void visitSubtractionExpression(SubtractionExpression<>& expr); 16 | virtual void visitMultiplicationExpression(MultiplicationExpression<>& expr); 17 | virtual void visitDivisionExpression(DivisionExpression<>& expr); 18 | virtual void visitIntegerExpression(IntegerExpression<>& expr); 19 | virtual void visitDoubleExpression(DoubleExpression<>& expr); 20 | virtual void visitStringExpression(StringExpression<>& expr); 21 | virtual void visitVariableExpression(VariableExpression<>& expr); 22 | virtual void visitBoolLiteral(BoolLiteral<>& expr); 23 | virtual void visitVoidLiteral(VoidLiteral<>& expr); 24 | virtual void visitNotExpression(NotExpression<>& expr); 25 | virtual void visitEqualityExpression(EqualityExpression<>& expr); 26 | virtual void visitInequalityExpression(InequalityExpression<>& expr); 27 | virtual void visitGtExpression(GtExpression<>& expr); 28 | virtual void visitGteExpression(GteExpression<>& expr); 29 | virtual void visitLtExpression(LtExpression<>& expr); 30 | virtual void visitLteExpression(LteExpression<>& expr); 31 | virtual void visitFuncCallExpression(FuncCallExpression<>& expr); 32 | virtual void visitListLiteralExpression(ListLiteralExpression<>& expr); 33 | virtual void visitDynamicAccessExpression(DynamicAccessExpression<>& expr); 34 | virtual void visitDynamicStoreExpression(DynamicStoreExpression<>& expr); 35 | virtual void visitStaticAccessExpression(StaticAccessExpression<>& expr); 36 | virtual void visitStaticStoreExpression(StaticStoreExpression<>& expr); 37 | virtual void visitExpressionStatement(ExpressionStatement<>& stmt); 38 | virtual void visitIfStatement(IfStatement<>& stmt); 39 | virtual void visitForCondition(ForCondition<>& stmt); 40 | virtual void visitReturnStatement(ReturnStatement<>& stmt); 41 | virtual void visitBlock(Block<>& expr); 42 | virtual void visitFuncDecl(FuncDecl<>& funcDecl); 43 | virtual void visitVarDecl(VarDecl<>& varDecl); 44 | 45 | 46 | }; 47 | 48 | }} 49 | 50 | #endif 51 | -------------------------------------------------------------------------------- /visitor/ssa_builder.h: -------------------------------------------------------------------------------- 1 | #ifndef VAIVEN_VISITOR_HEADER_SSA_BUILDER 2 | #define VAIVEN_VISITOR_HEADER_SSA_BUILDER 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include "../ast/visitor.h" 10 | #include "../ast/all.h" 11 | #include "../type_info.h" 12 | #include "../scope.h" 13 | #include "../ssa/ssa.h" 14 | #include "../ssa/cfg.h" 15 | #include "../function_usage.h" 16 | #include "../functions.h" 17 | 18 | namespace vaiven { namespace visitor { 19 | 20 | using namespace vaiven::ast; 21 | using std::stack; 22 | using std::map; 23 | using std::string; 24 | using std::unordered_set; 25 | 26 | class SsaBuilder : public Visitor<> { 27 | 28 | public: 29 | SsaBuilder(FunctionUsage& usageInfo, Functions& funcs) 30 | : usageInfo(usageInfo), funcs(funcs), curBlock(&head), cur(NULL), writePoint(NULL) {}; 31 | 32 | virtual void visitAssignmentExpression(AssignmentExpression<>& expr); 33 | virtual void visitAdditionExpression(AdditionExpression<>& expr); 34 | virtual void visitSubtractionExpression(SubtractionExpression<>& expr); 35 | virtual void visitMultiplicationExpression(MultiplicationExpression<>& expr); 36 | virtual void visitDivisionExpression(DivisionExpression<>& expr); 37 | virtual void visitIntegerExpression(IntegerExpression<>& expr); 38 | virtual void visitDoubleExpression(DoubleExpression<>& expr); 39 | virtual void visitStringExpression(StringExpression<>& expr); 40 | virtual void visitVariableExpression(VariableExpression<>& expr); 41 | virtual void visitBoolLiteral(BoolLiteral<>& expr); 42 | virtual void visitVoidLiteral(VoidLiteral<>& expr); 43 | virtual void visitNotExpression(NotExpression<>& expr); 44 | virtual void visitEqualityExpression(EqualityExpression<>& expr); 45 | virtual void visitInequalityExpression(InequalityExpression<>& expr); 46 | virtual void visitGtExpression(GtExpression<>& expr); 47 | virtual void visitGteExpression(GteExpression<>& expr); 48 | virtual void visitLtExpression(LtExpression<>& expr); 49 | virtual void visitLteExpression(LteExpression<>& expr); 50 | virtual void visitFuncCallExpression(FuncCallExpression<>& expr); 51 | virtual void visitListLiteralExpression(ListLiteralExpression<>& expr); 52 | virtual void visitDynamicAccessExpression(DynamicAccessExpression<>& expr); 53 | virtual void visitDynamicStoreExpression(DynamicStoreExpression<>& expr); 54 | virtual void visitStaticAccessExpression(StaticAccessExpression<>& expr); 55 | virtual void visitStaticStoreExpression(StaticStoreExpression<>& expr); 56 | virtual void visitExpressionStatement(ExpressionStatement<>& stmt); 57 | virtual void visitIfStatement(IfStatement<>& stmt); 58 | virtual void visitForCondition(ForCondition<>& stmt); 59 | virtual void visitReturnStatement(ReturnStatement<>& stmt); 60 | virtual void visitBlock(Block<>& expr); 61 | virtual void visitFuncDecl(FuncDecl<>& funcDecl); 62 | virtual void visitVarDecl(VarDecl<>& varDecl); 63 | 64 | void emit(ssa::Instruction* next); 65 | 66 | ssa::Block head; 67 | ssa::Block* curBlock; 68 | ssa::Instruction* cur; 69 | ssa::Instruction* writePoint; 70 | Scope scope; 71 | 72 | private: 73 | Functions& funcs; 74 | FunctionUsage& usageInfo; 75 | unordered_set varsToPhi; 76 | bool isReturnable; 77 | 78 | }; 79 | 80 | }} 81 | 82 | #endif 83 | --------------------------------------------------------------------------------