├── .gitignore ├── EnkelExamples ├── AllPrimitiveTypes.enk ├── Card.enk ├── CardDrawer.enk ├── ClassPathCalls │ ├── Client.enk │ └── Library.enk ├── ConstructorWithParams.enk ├── DefaultConstructor.enk ├── DefaultParams.enk ├── EqualitySyntax.enk ├── Fibonacci.enk ├── Fields.enk ├── HelloWorld.enk ├── Loops.enk ├── NamedParams.enk ├── ParameterLessConstructor.enk ├── Recursion.enk └── SumCalculator.enk ├── README.md ├── antlr ├── .gitignore ├── build.gradle ├── generated-src │ └── main │ │ └── java │ │ └── com │ │ └── bendcap │ │ └── enkel │ │ └── antlr │ │ ├── Enkel.tokens │ │ ├── EnkelBaseListener.java │ │ ├── EnkelBaseVisitor.java │ │ ├── EnkelLexer.java │ │ ├── EnkelLexer.tokens │ │ ├── EnkelListener.java │ │ ├── EnkelParser.java │ │ └── EnkelVisitor.java └── src │ └── main │ └── antlr │ └── com │ └── bendcap │ └── enkel │ └── antlr │ └── Enkel.g4 ├── compiler ├── .gitignore ├── build.gradle └── src │ └── main │ └── java │ └── com │ └── bendcap │ └── enkel │ └── compiler │ ├── bytecodegenerator │ ├── BytecodeGenerator.java │ ├── ClassGenerator.java │ ├── FieldGenerator.java │ ├── MethodGenerator.java │ ├── expression │ │ ├── ArithmeticExpressionGenerator.java │ │ ├── CallExpressionGenerator.java │ │ ├── ConditionalExpressionGenerator.java │ │ ├── ExpressionGenerator.java │ │ ├── ParameterExpressionGenerator.java │ │ ├── ReferenceExpressionGenerator.java │ │ └── ValueExpressionGenerator.java │ └── statement │ │ ├── AssignmentStatementGenerator.java │ │ ├── BlockStatementGenerator.java │ │ ├── ForStatementGenerator.java │ │ ├── IfStatementGenerator.java │ │ ├── PrintStatementGenerator.java │ │ ├── ReturnStatemenetGenerator.java │ │ ├── StatementGenerator.java │ │ └── VariableDeclarationStatementGenerator.java │ ├── compiler │ └── Compiler.java │ ├── domain │ ├── ClassDeclaration.java │ ├── CompareSign.java │ ├── CompilationUnit.java │ ├── Constructor.java │ ├── Function.java │ ├── MetaData.java │ ├── node │ │ ├── Node.java │ │ ├── expression │ │ │ ├── Argument.java │ │ │ ├── Call.java │ │ │ ├── ConditionalExpression.java │ │ │ ├── ConstructorCall.java │ │ │ ├── EmptyExpression.java │ │ │ ├── Expression.java │ │ │ ├── FieldReference.java │ │ │ ├── FunctionCall.java │ │ │ ├── LocalVariableReference.java │ │ │ ├── Parameter.java │ │ │ ├── Reference.java │ │ │ ├── SuperCall.java │ │ │ ├── Value.java │ │ │ └── arthimetic │ │ │ │ ├── Addition.java │ │ │ │ ├── ArthimeticExpression.java │ │ │ │ ├── Division.java │ │ │ │ ├── Multiplication.java │ │ │ │ └── Substraction.java │ │ └── statement │ │ │ ├── Assignment.java │ │ │ ├── Block.java │ │ │ ├── IfStatement.java │ │ │ ├── PrintStatement.java │ │ │ ├── RangedForStatement.java │ │ │ ├── ReturnStatement.java │ │ │ ├── Statement.java │ │ │ └── VariableDeclaration.java │ ├── scope │ │ ├── ClassPathScope.java │ │ ├── Field.java │ │ ├── FunctionSignature.java │ │ ├── LocalVariable.java │ │ ├── Scope.java │ │ └── Variable.java │ └── type │ │ ├── BultInType.java │ │ ├── ClassType.java │ │ ├── Type.java │ │ └── TypeSpecificOpcodes.java │ ├── exception │ ├── BadArgumentsToFunctionCallException.java │ ├── CalledFunctionDoesNotExistException.java │ ├── ClassNotFoundForNameException.java │ ├── ComparisonBetweenDiferentTypesException.java │ ├── CompilationException.java │ ├── FieldNotFoundException.java │ ├── FunctionNameEqualClassException.java │ ├── LastStatementNotReturnableException.java │ ├── LocalVariableNotFoundException.java │ ├── MethodSignatureNotFoundException.java │ ├── MethodWithNameAlreadyDefinedException.java │ ├── MixedComparisonNotAllowedException.java │ ├── NoVisitorReturnedValueException.java │ ├── ParameterForNameNotFoundException.java │ ├── UnsupportedArthimeticOperationException.java │ ├── UnsupportedRangedLoopTypes.java │ └── WrongArgumentNameException.java │ ├── parsing │ ├── EnkelTreeWalkErrorListener.java │ ├── Parser.java │ └── visitor │ │ ├── ClassVisitor.java │ │ ├── CompilationUnitVisitor.java │ │ ├── FieldVisitor.java │ │ ├── FunctionSignatureVisitor.java │ │ ├── FunctionVisitor.java │ │ ├── expression │ │ ├── ArithmeticExpressionVisitor.java │ │ ├── ConditionalExpressionVisitor.java │ │ ├── ExpressionVisitor.java │ │ ├── ValueExpressionVisitor.java │ │ ├── VariableReferenceExpressionVisitor.java │ │ └── function │ │ │ ├── ArgumentExpressionVisitor.java │ │ │ ├── ArgumentExpressionsListVisitor.java │ │ │ ├── CallExpressionVisitor.java │ │ │ ├── ParameterExpressionListVisitor.java │ │ │ └── ParameterExpressionVisitor.java │ │ └── statement │ │ ├── AssignmentStatementVisitor.java │ │ ├── BlockStatementVisitor.java │ │ ├── ForStatementVisitor.java │ │ ├── IfStatementVisitor.java │ │ ├── PrintStatementVisitor.java │ │ ├── ReturnStatementVisitor.java │ │ ├── StatementVisitor.java │ │ └── VariableDeclarationStatementVisitor.java │ ├── utils │ ├── DescriptorFactory.java │ ├── PrimitiveTypesWrapperFactory.java │ ├── ReflectionObjectToSignatureMapper.java │ ├── TypeChecker.java │ └── TypeResolver.java │ └── validation │ └── ARGUMENT_ERRORS.java ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | .gradle 2 | out 3 | .idea 4 | build 5 | *.class -------------------------------------------------------------------------------- /EnkelExamples/AllPrimitiveTypes.enk: -------------------------------------------------------------------------------- 1 | AllPrimitiveTypes { 2 | start() { 3 | var stringVar = "str" 4 | var booleanVar = false 5 | var integerVar = 2745 6 | var doubleVar = 2343.05 7 | print "stringVar=" + stringVar + ", booleanVar=" + booleanVar + ", integerVar=" + integerVar + ", doubleVar=" + doubleVar 8 | print 2.5+2.5 + " is the sum of 2.5 and 2.5" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /EnkelExamples/Card.enk: -------------------------------------------------------------------------------- 1 | Card { 2 | string color 3 | string pattern 4 | Card(string cardColor,string cardPattern) { 5 | color = cardColor 6 | pattern = cardPattern 7 | } 8 | string getColor() { 9 | color 10 | } 11 | string getPattern() { 12 | pattern 13 | } 14 | string toString() { 15 | return "{" + color + "," + pattern + "}" 16 | } 17 | } -------------------------------------------------------------------------------- /EnkelExamples/CardDrawer.enk: -------------------------------------------------------------------------------- 1 | CardDrawer { 2 | start { 3 | var cards = new List() 4 | addNumberedCards(cards) 5 | addCardWithAllColors("Ace",cards) 6 | addCardWithAllColors("Queen",cards) 7 | addCardWithAllColors("King",cards) 8 | addCardWithAllColors("Jack",cards) 9 | drawCardsForPlayers(playersAmount -> 5,cardsList -> cards) 10 | } 11 | addNumberedCards(List cardsList,int first=2, int last=10) { 12 | for i from first to last { 13 | var numberString = new java.lang.Integer(i).toString() 14 | addCardWithAllColors(numberString,cardsList) 15 | } 16 | } 17 | addCardWithAllColors(string pattern,List cardsList) { 18 | cardsList.add(new Card("Clubs",pattern)) 19 | cardsList.add(new Card("Diamonds",pattern)) 20 | cardsList.add(new Card("Hearts",pattern)) 21 | cardsList.add(new Card("Spades",pattern)) 22 | } 23 | drawCardsForPlayers(List cardsList,int playersAmount = 3,int cardsPerPlayer = 5) { 24 | if(cardsList.size() < (playersAmount * cardsPerPlayer)) { 25 | print "ERROR - Not enough cards" 26 | return 27 | } 28 | var random = new java.util.Random() 29 | for i from 1 to playersAmount { 30 | var playernumberString = new java.lang.Integer(i).toString() 31 | print "player " + playernumberString + " is drawing:" 32 | for j from 1 to cardsPerPlayer { 33 | var dawnCardIndex = random.nextInt(cardsList.size() - 1) 34 | var drawedCard = cardsList.remove(dawnCardIndex) 35 | print " drawed:" + drawedCard 36 | } 37 | } 38 | } 39 | } -------------------------------------------------------------------------------- /EnkelExamples/ClassPathCalls/Client.enk: -------------------------------------------------------------------------------- 1 | Client { 2 | 3 | start { 4 | var someString = "someString" 5 | print someString + " to upper case : " + someString.toUpperCase() 6 | 7 | print "Client: Calling my own 'Library' class:" 8 | var myLibrary = new Library() 9 | var addition = myLibrary.add(5,2) 10 | print "Client: Result returned from 'Library.add' = " + addition 11 | } 12 | 13 | } -------------------------------------------------------------------------------- /EnkelExamples/ClassPathCalls/Library.enk: -------------------------------------------------------------------------------- 1 | Library { 2 | int add(int x,int y) { 3 | print "Library: add() method called" 4 | return x+y 5 | } 6 | } -------------------------------------------------------------------------------- /EnkelExamples/ConstructorWithParams.enk: -------------------------------------------------------------------------------- 1 | ConstructorWithParams { 2 | 3 | ConstructorWithParams(int x) { 4 | print "Hey I am constructor with parameter x = " + x 5 | } 6 | 7 | start() { 8 | var instance = new ConstructorWithParams(5) 9 | instance.doStuff(2) 10 | instance.doStuff(4) 11 | } 12 | 13 | doStuff(int y) { 14 | print "doing stuff on ConstructorWithParams instance" + " y = " + y 15 | } 16 | } -------------------------------------------------------------------------------- /EnkelExamples/DefaultConstructor.enk: -------------------------------------------------------------------------------- 1 | DefaultConstructor { 2 | start() { 3 | print "Hey I am 'start' method. I am not static so the default constructor must have been called, even though it is not defined" 4 | } 5 | } -------------------------------------------------------------------------------- /EnkelExamples/DefaultParams.enk: -------------------------------------------------------------------------------- 1 | DefaultParamTest { 2 | start() { 3 | greet("andrew") 4 | print "" 5 | greet("kuba","enkel") 6 | } 7 | greet (string name,string favouriteLanguage="java") { 8 | print "Hello my name is " 9 | print name 10 | print "and my favourite langugage is " 11 | print favouriteLanguage 12 | } 13 | } -------------------------------------------------------------------------------- /EnkelExamples/EqualitySyntax.enk: -------------------------------------------------------------------------------- 1 | EqualitySyntax { 2 | start { 3 | objectComparisonTest() 4 | primitiveComparisonTest() 5 | primitiveComparisonTest2() 6 | objectComparisonTest2() 7 | } 8 | primitiveComparisonTest { 9 | var a = 3 10 | var b = 3 11 | print "Comparing primitive " + a +" and " + b 12 | var result = a == b 13 | assert(expected -> true , actual -> result) 14 | var result = a != b 15 | assert(expected -> false , actual -> result) 16 | var result = a > b 17 | assert(expected -> false , actual -> result) 18 | var result = a < b 19 | assert(expected -> false , actual -> result) 20 | var result = a >= b 21 | assert(expected -> true , actual -> result) 22 | var result = a <= b 23 | assert(expected -> true , actual -> result) 24 | } 25 | objectComparisonTest() { 26 | var a = new java.lang.Integer(3) 27 | var b = new java.lang.Integer(3) 28 | print "Comparing integer " + a.toString() +" and " + b.toString() 29 | var result = a == b 30 | assert(expected -> true , actual -> result) 31 | var result = a != b 32 | assert(expected -> false , actual -> result) 33 | var result = a > b 34 | assert(expected -> false , actual -> result) 35 | var result = a < b 36 | assert(expected -> false , actual -> result) 37 | var result = a >= b 38 | assert(expected -> true , actual -> result) 39 | var result = a <= b 40 | assert(expected -> true , actual -> result) 41 | } 42 | primitiveComparisonTest2 { 43 | var a = 3 44 | var b = 4 45 | print "Comparing primitive " + a +" and " + b 46 | var result = a == b 47 | assert(expected -> false , actual -> result) 48 | var result = a != b 49 | assert(expected -> true , actual -> result) 50 | var result = a > b 51 | assert(expected -> false , actual -> result) 52 | var result = a < b 53 | assert(expected -> true , actual -> result) 54 | var result = a >= b 55 | assert(expected -> false , actual -> result) 56 | var result = a <= b 57 | assert(expected -> true , actual -> result) 58 | } 59 | objectComparisonTest2() { 60 | var a = new java.lang.Integer(3) 61 | var b = new java.lang.Integer(4) 62 | print "Comparing integer " + a.toString() +" and " + b.toString() 63 | var result = a == b 64 | assert(expected -> false , actual -> result) 65 | var result = a != b 66 | assert(expected -> true , actual -> result) 67 | var result = a > b 68 | assert(expected -> false , actual -> result) 69 | var result = a < b 70 | assert(expected -> true , actual -> result) 71 | var result = a >= b 72 | assert(expected -> false , actual -> result) 73 | 74 | var result = a <= b 75 | assert(actual -> result, expected -> true ) 76 | } 77 | void assert(boolean actual,boolean expected) { 78 | if (actual == expected) { 79 | print "OK" 80 | } 81 | else { 82 | print "TEST FAILED" 83 | } 84 | } 85 | } -------------------------------------------------------------------------------- /EnkelExamples/Fibonacci.enk: -------------------------------------------------------------------------------- 1 | Fibonacci { 2 | int i 3 | int n 4 | int t1 5 | int t2 6 | int nextTerm 7 | start { 8 | t1 = 0 9 | t2 = 1 10 | n = 10 11 | for x from 1 to n { 12 | print "t" + t1 13 | nextTerm = t1 + t2 14 | t1 = t2 15 | t2 = nextTerm 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /EnkelExamples/Fields.enk: -------------------------------------------------------------------------------- 1 | Fields { 2 | int field 3 | start { 4 | field = 5 5 | print field 6 | } 7 | } -------------------------------------------------------------------------------- /EnkelExamples/HelloWorld.enk: -------------------------------------------------------------------------------- 1 | HelloWorld { 2 | start() { 3 | print "hello world!" 4 | } 5 | } -------------------------------------------------------------------------------- /EnkelExamples/Loops.enk: -------------------------------------------------------------------------------- 1 | Loops { 2 | start() { 3 | print "incrementing from 1 to 10" 4 | for x from 1 to 10 { 5 | print x 6 | } 7 | 8 | print "decrementing from 10 to 1" 9 | for x from 10 to 1 { 10 | print x 11 | } 12 | } 13 | } -------------------------------------------------------------------------------- /EnkelExamples/NamedParams.enk: -------------------------------------------------------------------------------- 1 | NamedParamsTest { 2 | start() { 3 | createRectangle(x1->25,x2-> -25,y1->50,y2->-50) 4 | createRectangle(25,50,-25,-50) 5 | otherStuff() 6 | } 7 | 8 | otherStuff() { 9 | return 10 | } 11 | 12 | createRectangle (int x1,int y1,int x2, int y2) { 13 | print "x1=" + x1 14 | print "x2=" + x2 15 | print "y1=" + y1 16 | print "y2=" + y2 17 | } 18 | } -------------------------------------------------------------------------------- /EnkelExamples/ParameterLessConstructor.enk: -------------------------------------------------------------------------------- 1 | ParameterLessConstructor { 2 | ParameterLessConstructor() { 3 | print "Hey I am constructor without parameters" 4 | } 5 | start() { 6 | doStuff() 7 | } 8 | doStuff() { 9 | print "doing stuff on ParameterLessConstructor object" 10 | } 11 | } -------------------------------------------------------------------------------- /EnkelExamples/Recursion.enk: -------------------------------------------------------------------------------- 1 | Recursion { 2 | int result 3 | int tmp 4 | int tmpN 5 | int sum(int num) { 6 | if (num != 0) { 7 | tmpN = num - 1 8 | return num + sum(tmpN) 9 | } else { 10 | return num 11 | } 12 | } 13 | 14 | void start() { 15 | result = sum(10) 16 | print "result=" + result 17 | } 18 | } -------------------------------------------------------------------------------- /EnkelExamples/SumCalculator.enk: -------------------------------------------------------------------------------- 1 | SumCalculator { 2 | start () { 3 | var expected = 8 4 | var actual = sum(3,5) 5 | 6 | if( actual == expected ) { 7 | print "test passed" 8 | } else { 9 | print "test failed" 10 | } 11 | } 12 | 13 | int sum (int x ,int y) { 14 | x+y 15 | } 16 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Enkel (JVM based language) 2 | ======= 3 | 4 | Enkel is a simple programming language running on the jvm 5 | 6 | 7 | ## Build & Run 8 | - Generate parser code from ANTLR 9 | `./gradlew :antlr:generateGrammarSource ` 10 | 11 | - Compile `*.enk` to `*.class` 12 | Using IDEA 13 | 14 | - Run 15 | `java *.class` 16 | 17 | ## Example 18 | 19 | - Input(`Fields.enl`) 20 | ``` 21 | Fields { 22 | int field 23 | start { 24 | field = 5 25 | print field 26 | } 27 | } 28 | ``` 29 | 30 | - Output(`Fields.class`) 31 | 32 | Decompiled form: 33 | ``` 34 | public class Fields { 35 | public int field; 36 | 37 | public void start() { 38 | this.field = 5; 39 | System.out.println(this.field); 40 | } 41 | 42 | public Fields() { 43 | } 44 | 45 | public static void main(String[] var0) { 46 | (new Fields()).start(); 47 | } 48 | } 49 | ``` 50 | 51 | Other examples please see `./EnkelExamples/*.enk` 52 | 53 | ## TODO 54 | - [ ] Other grammar feature 55 | - [ ] IDEA highlight plugin 56 | - [ ] Support debugger 57 | - [ ] Port to LLVM IR -------------------------------------------------------------------------------- /antlr/.gitignore: -------------------------------------------------------------------------------- 1 | build 2 | out -------------------------------------------------------------------------------- /antlr/build.gradle: -------------------------------------------------------------------------------- 1 | group GROUP 2 | version VERSION 3 | 4 | apply plugin: 'java' 5 | apply plugin: 'antlr' 6 | 7 | sourceCompatibility = 1.8 8 | 9 | repositories { 10 | mavenCentral() 11 | } 12 | 13 | configurations { 14 | compile { 15 | extendsFrom = extendsFrom.findAll { it != configurations.antlr } 16 | } 17 | } 18 | 19 | dependencies { 20 | testCompile group: 'junit', name: 'junit', version: '4.12' 21 | antlr "org.antlr:antlr4:4.3" // use ANTLR version 4, default is 2.x which is wrong 22 | compile "org.antlr:antlr4-runtime:4.3" 23 | } 24 | 25 | generateGrammarSource { 26 | maxHeapSize = "64m" 27 | arguments += ["-visitor", "-long-messages"] 28 | // Keep a copy of generated sources 29 | doLast { 30 | println "Copying generated grammar lexer/parser files to main directory." 31 | copy { 32 | from "${buildDir}/generated-src/antlr/main" 33 | into "generated-src/main/java" 34 | } 35 | } 36 | } 37 | 38 | clean.doLast { 39 | file('generated-src').deleteDir() 40 | } 41 | -------------------------------------------------------------------------------- /antlr/generated-src/main/java/com/bendcap/enkel/antlr/Enkel.tokens: -------------------------------------------------------------------------------- 1 | PRINT=39 2 | T__19=18 3 | T__15=22 4 | T__16=21 5 | T__17=20 6 | VARIABLE=38 7 | T__18=19 8 | T__33=4 9 | T__11=26 10 | T__3=34 11 | T__34=3 12 | T__12=25 13 | T__2=35 14 | T__35=2 15 | T__13=24 16 | T__1=36 17 | T__36=1 18 | T__14=23 19 | T__0=37 20 | ID=44 21 | WS=45 22 | T__30=7 23 | T__31=6 24 | T__32=5 25 | T__10=27 26 | T__9=28 27 | NUMBER=41 28 | T__8=29 29 | T__7=30 30 | EQUALS=40 31 | T__6=31 32 | T__5=32 33 | T__4=33 34 | T__26=11 35 | T__27=10 36 | BOOL=42 37 | T__28=9 38 | T__29=8 39 | T__22=15 40 | T__23=14 41 | STRING=43 42 | T__24=13 43 | T__25=12 44 | T__20=17 45 | T__21=16 46 | '-'=37 47 | '+'=36 48 | ')'=35 49 | 'super'=34 50 | 'else'=33 51 | 'string'=32 52 | '>'=31 53 | ']'=30 54 | '=='=28 55 | '<'=29 56 | '>='=26 57 | '['=27 58 | 'to'=25 59 | 'long'=24 60 | 'boolean'=23 61 | 'var'=38 62 | '->'=22 63 | '.'=21 64 | ','=20 65 | '*'=19 66 | '('=18 67 | 'print'=39 68 | 'from'=16 69 | 'int'=17 70 | 'double'=15 71 | 'short'=14 72 | '<='=13 73 | 'for'=11 74 | 'if'=12 75 | '}'=10 76 | '='=40 77 | 'byte'=9 78 | 'void'=7 79 | '{'=8 80 | 'float'=6 81 | '!='=5 82 | 'new'=3 83 | 'return'=4 84 | 'char'=2 85 | '/'=1 86 | -------------------------------------------------------------------------------- /antlr/generated-src/main/java/com/bendcap/enkel/antlr/EnkelLexer.tokens: -------------------------------------------------------------------------------- 1 | PRINT=39 2 | T__19=18 3 | T__15=22 4 | T__16=21 5 | T__17=20 6 | VARIABLE=38 7 | T__18=19 8 | T__33=4 9 | T__11=26 10 | T__3=34 11 | T__34=3 12 | T__12=25 13 | T__2=35 14 | T__35=2 15 | T__13=24 16 | T__1=36 17 | T__36=1 18 | T__14=23 19 | T__0=37 20 | ID=44 21 | WS=45 22 | T__30=7 23 | T__31=6 24 | T__32=5 25 | T__10=27 26 | T__9=28 27 | NUMBER=41 28 | T__8=29 29 | T__7=30 30 | EQUALS=40 31 | T__6=31 32 | T__5=32 33 | T__4=33 34 | T__26=11 35 | T__27=10 36 | BOOL=42 37 | T__28=9 38 | T__29=8 39 | T__22=15 40 | T__23=14 41 | STRING=43 42 | T__24=13 43 | T__25=12 44 | T__20=17 45 | T__21=16 46 | '-'=37 47 | '+'=36 48 | ')'=35 49 | 'super'=34 50 | 'else'=33 51 | 'string'=32 52 | '>'=31 53 | ']'=30 54 | '=='=28 55 | '<'=29 56 | '>='=26 57 | '['=27 58 | 'to'=25 59 | 'long'=24 60 | 'boolean'=23 61 | 'var'=38 62 | '->'=22 63 | '.'=21 64 | ','=20 65 | '*'=19 66 | '('=18 67 | 'print'=39 68 | 'from'=16 69 | 'int'=17 70 | 'double'=15 71 | 'short'=14 72 | '<='=13 73 | 'for'=11 74 | 'if'=12 75 | '}'=10 76 | '='=40 77 | 'byte'=9 78 | 'void'=7 79 | '{'=8 80 | 'float'=6 81 | '!='=5 82 | 'new'=3 83 | 'return'=4 84 | 'char'=2 85 | '/'=1 86 | -------------------------------------------------------------------------------- /antlr/src/main/antlr/com/bendcap/enkel/antlr/Enkel.g4: -------------------------------------------------------------------------------- 1 | //header 2 | grammar Enkel; 3 | 4 | @header { 5 | package com.bendcap.enkel.antlr; 6 | } 7 | 8 | //RULES 9 | compilationUnit : classDeclaration EOF ; 10 | classDeclaration : className '{' classBody '}' ; 11 | className : qualifiedName ; 12 | classBody : field* function* ; 13 | field : type name; 14 | function : functionDeclaration block; 15 | functionDeclaration : (type)? functionName '('? parametersList? ')'? ; 16 | parametersList: parameter (',' parameter)* 17 | | parameter (',' parameterWithDefaultValue)* 18 | | parameterWithDefaultValue (',' parameterWithDefaultValue)* ; 19 | functionName : ID ; 20 | parameter : type ID ; 21 | parameterWithDefaultValue : type ID '=' defaultValue=expression ; 22 | type : primitiveType 23 | | classType ; 24 | 25 | primitiveType : 'boolean' ('[' ']')* 26 | | 'string' ('[' ']')* 27 | | 'char' ('[' ']')* 28 | | 'byte' ('[' ']')* 29 | | 'short' ('[' ']')* 30 | | 'int' ('[' ']')* 31 | | 'long' ('[' ']')* 32 | | 'float' ('[' ']')* 33 | | 'double' ('[' ']')* 34 | | 'void' ('[' ']')* ; 35 | classType : qualifiedName ('[' ']')* ; 36 | 37 | block : '{' statement* '}' ; 38 | 39 | statement : block 40 | | variableDeclaration 41 | | assignment 42 | | printStatement 43 | | forStatement 44 | | returnStatement 45 | | ifStatement 46 | | expression ; 47 | 48 | variableDeclaration : VARIABLE name EQUALS expression ; 49 | assignment : name EQUALS expression; 50 | printStatement : PRINT expression ; 51 | returnStatement : 'return' expression #ReturnWithValue 52 | | 'return' #ReturnVoid ; 53 | 54 | ifStatement: 'if' ('(')? expression (')')? trueStatement=statement ('else' falseStatement=statement)?; 55 | 56 | forStatement : 'for' ('(')? forConditions (')')? statement ; 57 | forConditions : iterator=variableReference 'from' startExpr=expression range='to' endExpr=expression ; 58 | 59 | name : ID ; 60 | argumentList : argument? (',' a=argument)* #UnnamedArgumentsList 61 | | namedArgument? (',' namedArgument)* #NamedArgumentsList ; 62 | argument : expression ; 63 | namedArgument : name '->' expression ; 64 | 65 | expression : variableReference #VarReference 66 | | owner=expression '.' functionName '(' argumentList ')' #FunctionCall 67 | | functionName '(' argumentList ')' #FunctionCall 68 | | superCall='super' '('argumentList ')' #Supercall 69 | | newCall='new' className '('argumentList ')' #ConstructorCall 70 | | value #ValueExpr 71 | | '('expression '*' expression')' #Multiply 72 | | expression '*' expression #Multiply 73 | | '(' expression '/' expression ')' #Divide 74 | | expression '/' expression #Divide 75 | | '(' expression '+' expression ')' #Add 76 | | expression '+' expression #Add 77 | | '(' expression '-' expression ')' #Substract 78 | | expression '-' expression #Substract 79 | | expression cmp='>' expression #ConditionalExpression 80 | | expression cmp='<' expression #ConditionalExpression 81 | | expression cmp='==' expression #ConditionalExpression 82 | | expression cmp='!=' expression #ConditionalExpression 83 | | expression cmp='>=' expression #ConditionalExpression 84 | | expression cmp='<=' expression #ConditionalExpression 85 | ; 86 | 87 | variableReference : ID ; 88 | value : NUMBER 89 | | BOOL 90 | | STRING ; 91 | qualifiedName : ID ('.' ID)*; 92 | 93 | //TOKENS 94 | VARIABLE : 'var' ; 95 | PRINT : 'print' ; 96 | EQUALS : '=' ; 97 | NUMBER : '-'?[0-9.]+ ; 98 | BOOL : 'true' | 'false' ; 99 | STRING : '"'~('\r' | '\n' | '"')*'"' ; 100 | ID : [a-zA-Z0-9]+ ; 101 | WS: [ \t\n\r]+ -> skip ; -------------------------------------------------------------------------------- /compiler/.gitignore: -------------------------------------------------------------------------------- 1 | build 2 | out 3 | *.iml -------------------------------------------------------------------------------- /compiler/build.gradle: -------------------------------------------------------------------------------- 1 | group GROUP 2 | version VERSION 3 | 4 | apply plugin: 'java' 5 | 6 | sourceCompatibility = 1.8 7 | 8 | repositories { 9 | mavenCentral() 10 | } 11 | 12 | dependencies { 13 | testCompile group: 'junit', name: 'junit', version: '4.12' 14 | compile project(':antlr') 15 | compile 'org.ow2.asm:asm:5.1' 16 | compile 'org.apache.commons:commons-lang3:3.4' 17 | compile 'commons-io:commons-io:2.4' 18 | compile 'com.google.guava:guava:19.0' 19 | compile 'commons-validator:commons-validator:1.3.1' 20 | compile "org.projectlombok:lombok:1.18.0" 21 | compile 'org.apache.commons:commons-collections4:4.1' 22 | } 23 | -------------------------------------------------------------------------------- /compiler/src/main/java/com/bendcap/enkel/compiler/bytecodegenerator/BytecodeGenerator.java: -------------------------------------------------------------------------------- 1 | package com.bendcap.enkel.compiler.bytecodegenerator; 2 | 3 | import com.bendcap.enkel.compiler.domain.ClassDeclaration; 4 | import com.bendcap.enkel.compiler.domain.CompilationUnit; 5 | 6 | /** 7 | * Created by KevinOfNeu on 2018/8/22 11:49. 8 | */ 9 | public class BytecodeGenerator { 10 | public byte[] generate(CompilationUnit compilationUnit) { 11 | ClassDeclaration classDeclaration = compilationUnit.getClassDeclaration(); 12 | ClassGenerator classGenerator = new ClassGenerator(); 13 | return classGenerator.generate(classDeclaration).toByteArray(); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /compiler/src/main/java/com/bendcap/enkel/compiler/bytecodegenerator/ClassGenerator.java: -------------------------------------------------------------------------------- 1 | package com.bendcap.enkel.compiler.bytecodegenerator; 2 | 3 | import com.bendcap.enkel.compiler.domain.Function; 4 | import com.bendcap.enkel.compiler.domain.ClassDeclaration; 5 | import com.bendcap.enkel.compiler.domain.scope.Field; 6 | import org.objectweb.asm.ClassWriter; 7 | import org.objectweb.asm.Opcodes; 8 | 9 | import java.util.Collection; 10 | import java.util.List; 11 | 12 | /** 13 | * Created by KevinOfNeu on 2018/8/22 11:50. 14 | */ 15 | public class ClassGenerator { 16 | private static final int CLASS_VERSION = 52; 17 | private ClassWriter classWriter; 18 | 19 | public ClassGenerator() { 20 | classWriter = new ClassWriter(ClassWriter.COMPUTE_FRAMES + ClassWriter.COMPUTE_MAXS); 21 | } 22 | 23 | public ClassWriter generate(ClassDeclaration classDeclaration) { 24 | String name = classDeclaration.getName(); 25 | classWriter.visit( 26 | CLASS_VERSION, 27 | Opcodes.ACC_PUBLIC + Opcodes.ACC_SUPER, 28 | name, 29 | null, 30 | "java/lang/Object", 31 | null 32 | ); 33 | List methods = classDeclaration.getMethods(); 34 | Collection fields = classDeclaration.getFields(); 35 | FieldGenerator fieldGenerator = new FieldGenerator(classWriter); 36 | fields.forEach(f -> f.accept(fieldGenerator)); 37 | MethodGenerator methodGenerator = new MethodGenerator(classWriter); 38 | methods.forEach(f -> f.accept(methodGenerator)); 39 | classWriter.visitEnd(); 40 | return classWriter; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /compiler/src/main/java/com/bendcap/enkel/compiler/bytecodegenerator/FieldGenerator.java: -------------------------------------------------------------------------------- 1 | package com.bendcap.enkel.compiler.bytecodegenerator; 2 | 3 | import com.bendcap.enkel.compiler.domain.scope.Field; 4 | import org.objectweb.asm.ClassWriter; 5 | import org.objectweb.asm.FieldVisitor; 6 | import org.objectweb.asm.Opcodes; 7 | 8 | /** 9 | * Created by KevinOfNeu on 2018/8/31 22:15. 10 | */ 11 | public class FieldGenerator { 12 | private final ClassWriter classWriter; 13 | 14 | public FieldGenerator(ClassWriter classWriter) { 15 | this.classWriter = classWriter; 16 | } 17 | 18 | public void generate(Field field) { 19 | String name = field.getName(); 20 | String descriptor = field.getType().getDescriptor(); 21 | FieldVisitor fieldVisitor = classWriter.visitField(Opcodes.ACC_PUBLIC, name, descriptor, null, null); 22 | fieldVisitor.visitEnd(); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /compiler/src/main/java/com/bendcap/enkel/compiler/bytecodegenerator/MethodGenerator.java: -------------------------------------------------------------------------------- 1 | package com.bendcap.enkel.compiler.bytecodegenerator; 2 | 3 | import com.bendcap.enkel.compiler.bytecodegenerator.statement.StatementGenerator; 4 | import com.bendcap.enkel.compiler.domain.Constructor; 5 | import com.bendcap.enkel.compiler.domain.Function; 6 | import com.bendcap.enkel.compiler.domain.node.expression.EmptyExpression; 7 | import com.bendcap.enkel.compiler.domain.node.expression.SuperCall; 8 | import com.bendcap.enkel.compiler.domain.scope.Scope; 9 | import com.bendcap.enkel.compiler.domain.node.statement.Block; 10 | import com.bendcap.enkel.compiler.domain.node.statement.ReturnStatement; 11 | import com.bendcap.enkel.compiler.domain.node.statement.Statement; 12 | import org.objectweb.asm.ClassWriter; 13 | import com.bendcap.enkel.compiler.utils.DescriptorFactory; 14 | import org.objectweb.asm.MethodVisitor; 15 | import org.objectweb.asm.Opcodes; 16 | 17 | /** 18 | * Created by KevinOfNeu on 2018/8/22 15:44. 19 | */ 20 | public class MethodGenerator { 21 | public static final String MAIN_FUN_NAME = "main"; 22 | private ClassWriter classWriter; 23 | 24 | public MethodGenerator(ClassWriter classWriter) { 25 | this.classWriter = classWriter; 26 | } 27 | 28 | public void generate(Function function) { 29 | String name = function.getName(); 30 | boolean isMain = name.equals(MAIN_FUN_NAME); 31 | String description = DescriptorFactory.getMethodDescriptor(function); 32 | Block block = (Block) function.getRootStatement(); 33 | Scope scope = block.getScope(); 34 | int access = Opcodes.ACC_PUBLIC + (isMain ? Opcodes.ACC_STATIC : 0); 35 | MethodVisitor mv = classWriter.visitMethod(access, name, description, null, null); 36 | mv.visitCode(); 37 | StatementGenerator statementGenerator = new StatementGenerator(mv, scope); 38 | block.accept(statementGenerator); 39 | appendReturnIfNotExists(function, block, statementGenerator); 40 | mv.visitMaxs(-1, -1); 41 | mv.visitEnd(); 42 | } 43 | 44 | 45 | public void generate(Constructor constructor) { 46 | Block block = (Block) constructor.getRootStatement(); 47 | Scope scope = block.getScope(); 48 | int access = Opcodes.ACC_PUBLIC; 49 | String description = DescriptorFactory.getMethodDescriptor(constructor); 50 | MethodVisitor mv = classWriter.visitMethod(access, "", description, null, null); 51 | mv.visitCode(); 52 | StatementGenerator statementScopeGenerator = new StatementGenerator(mv, scope); 53 | new SuperCall().accept(statementScopeGenerator); 54 | block.accept(statementScopeGenerator); 55 | appendReturnIfNotExists(constructor, block, statementScopeGenerator); 56 | mv.visitMaxs(-1, -1); 57 | mv.visitEnd(); 58 | } 59 | 60 | 61 | private void appendReturnIfNotExists(Function function, Block block, StatementGenerator statementScopeGenrator) { 62 | boolean isLastStatementReturn = false; 63 | if(!block.getStatements().isEmpty()) { 64 | Statement lastStatement = block.getStatements().get(block.getStatements().size() - 1); 65 | isLastStatementReturn = lastStatement instanceof ReturnStatement; 66 | } 67 | if(!isLastStatementReturn) { 68 | EmptyExpression emptyExpression = new EmptyExpression(function.getReturnType()); 69 | ReturnStatement returnStatement = new ReturnStatement(emptyExpression); 70 | returnStatement.accept(statementScopeGenrator); 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /compiler/src/main/java/com/bendcap/enkel/compiler/bytecodegenerator/expression/ArithmeticExpressionGenerator.java: -------------------------------------------------------------------------------- 1 | package com.bendcap.enkel.compiler.bytecodegenerator.expression; 2 | 3 | import com.bendcap.enkel.compiler.domain.node.expression.arthimetic.*; 4 | import com.bendcap.enkel.compiler.domain.node.expression.Expression; 5 | import com.bendcap.enkel.compiler.domain.type.BultInType; 6 | import com.bendcap.enkel.compiler.domain.type.Type; 7 | import org.objectweb.asm.MethodVisitor; 8 | import org.objectweb.asm.Opcodes; 9 | 10 | /** 11 | * Created by KevinOfNeu on 2018/8/31 11:37. 12 | */ 13 | public class ArithmeticExpressionGenerator { 14 | private final ExpressionGenerator expressionGenerator; 15 | private final MethodVisitor methodVisitor; 16 | 17 | public ArithmeticExpressionGenerator(ExpressionGenerator expressionGenerator, MethodVisitor methodVisitor) { 18 | this.expressionGenerator = expressionGenerator; 19 | this.methodVisitor = methodVisitor; 20 | } 21 | 22 | public void generate(Addition expression) { 23 | if (expression.getType().equals(BultInType.STRING)) { 24 | generateStringAppend(expression); 25 | return; 26 | } 27 | evaluateArithmeticComponents(expression); 28 | Type type = expression.getType(); 29 | methodVisitor.visitInsn(type.getAddOpcode()); 30 | } 31 | 32 | public void generate(Substraction expression) { 33 | Type type = expression.getType(); 34 | evaluateArithmeticComponents(expression); 35 | methodVisitor.visitInsn(type.getSubstractOpcode()); 36 | } 37 | 38 | public void generate(Multiplication expression) { 39 | evaluateArithmeticComponents(expression); 40 | Type type = expression.getType(); 41 | methodVisitor.visitInsn(type.getMultiplyOpcode()); 42 | } 43 | 44 | public void generate(Division expression) { 45 | evaluateArithmeticComponents(expression); 46 | Type type = expression.getType(); 47 | methodVisitor.visitInsn(type.getDividOpcode()); 48 | } 49 | 50 | private void evaluateArithmeticComponents(ArthimeticExpression expression) { 51 | Expression leftExpression = expression.getLeftExpression(); 52 | Expression rightExpression = expression.getRightExpression(); 53 | leftExpression.accept(expressionGenerator); 54 | rightExpression.accept(expressionGenerator); 55 | } 56 | 57 | private void generateStringAppend(Addition expression) { 58 | methodVisitor.visitTypeInsn(Opcodes.NEW, "java/lang/StringBuilder"); 59 | methodVisitor.visitInsn(Opcodes.DUP); 60 | methodVisitor.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/StringBuilder", "", "()V", false); 61 | Expression leftExpression = expression.getLeftExpression(); 62 | leftExpression.accept(expressionGenerator); 63 | String leftExprDescriptor = leftExpression.getType().getDescriptor(); 64 | String descriptor = "(" + leftExprDescriptor + ")Ljava/lang/StringBuilder;"; 65 | methodVisitor.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/StringBuilder", "append", descriptor, false); 66 | Expression rightExpression = expression.getRightExpression(); 67 | rightExpression.accept(expressionGenerator); 68 | String rightExprDescriptor = rightExpression.getType().getDescriptor(); 69 | descriptor = "(" + rightExprDescriptor + ")Ljava/lang/StringBuilder;"; 70 | methodVisitor.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/StringBuilder", "append", descriptor, false); 71 | methodVisitor.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/StringBuilder", "toString", "()Ljava/lang/String;", false); 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /compiler/src/main/java/com/bendcap/enkel/compiler/bytecodegenerator/expression/CallExpressionGenerator.java: -------------------------------------------------------------------------------- 1 | package com.bendcap.enkel.compiler.bytecodegenerator.expression; 2 | 3 | import com.bendcap.enkel.compiler.domain.node.expression.*; 4 | import com.bendcap.enkel.compiler.domain.scope.FunctionSignature; 5 | import com.bendcap.enkel.compiler.domain.scope.Scope; 6 | import com.bendcap.enkel.compiler.domain.type.ClassType; 7 | import com.bendcap.enkel.compiler.exception.BadArgumentsToFunctionCallException; 8 | import com.bendcap.enkel.compiler.exception.WrongArgumentNameException; 9 | import com.bendcap.enkel.compiler.utils.DescriptorFactory; 10 | import com.google.common.collect.Ordering; 11 | import org.objectweb.asm.MethodVisitor; 12 | import org.objectweb.asm.Opcodes; 13 | 14 | import java.util.Comparator; 15 | import java.util.List; 16 | import java.util.Optional; 17 | 18 | /** 19 | * Created by KevinOfNeu on 2018/8/31 13:11. 20 | */ 21 | public class CallExpressionGenerator { 22 | private final ExpressionGenerator expressionGenerator; 23 | private final Scope scope; 24 | private final MethodVisitor methodVisitor; 25 | 26 | public CallExpressionGenerator(ExpressionGenerator expressionGenerator, Scope scope, MethodVisitor methodVisitor) { 27 | this.expressionGenerator = expressionGenerator; 28 | this.scope = scope; 29 | this.methodVisitor = methodVisitor; 30 | } 31 | 32 | public void generate(ConstructorCall constructorCall) { 33 | FunctionSignature signature = scope.getConstructorCallSignature(constructorCall.getIdentifier(), constructorCall.getArguments()); 34 | String ownerDescriptor = new ClassType(signature.getName()).getDescriptor(); 35 | methodVisitor.visitTypeInsn(Opcodes.NEW, ownerDescriptor); 36 | methodVisitor.visitInsn(Opcodes.DUP); 37 | String methodDescriptor = DescriptorFactory.getMethodDescriptor(signature); 38 | generateArguments(constructorCall,signature); 39 | methodVisitor.visitMethodInsn(Opcodes.INVOKESPECIAL, ownerDescriptor, "", methodDescriptor, false); 40 | } 41 | 42 | public void generate(SuperCall superCall) { 43 | methodVisitor.visitVarInsn(Opcodes.ALOAD, 0); 44 | generateArguments(superCall); 45 | String ownerDescriptor = scope.getSuperClassInternalName(); 46 | methodVisitor.visitMethodInsn(Opcodes.INVOKESPECIAL, ownerDescriptor, "", "()V" /*TODO Handle super calls with arguments*/, false); 47 | } 48 | 49 | public void generate(FunctionCall functionCall) { 50 | Expression owner = functionCall.getOwner(); 51 | owner.accept(expressionGenerator); 52 | generateArguments(functionCall); 53 | String functionName = functionCall.getIdentifier(); 54 | String methodDescriptor = DescriptorFactory.getMethodDescriptor(functionCall.getSignature()); 55 | String ownerDescriptor = functionCall.getOwnerType().getInternalName(); 56 | methodVisitor.visitMethodInsn(Opcodes.INVOKEVIRTUAL, ownerDescriptor, functionName, methodDescriptor, false); 57 | } 58 | 59 | private void generateArguments(FunctionCall call) { 60 | FunctionSignature signature = scope.getMethodCallSignature(Optional.of(call.getOwnerType()),call.getIdentifier(),call.getArguments()); 61 | generateArguments(call,signature); 62 | } 63 | 64 | private void generateArguments(SuperCall call) { 65 | FunctionSignature signature = scope.getMethodCallSignature(call.getIdentifier(),call.getArguments()); 66 | generateArguments(call,signature); 67 | } 68 | 69 | private void generateArguments(ConstructorCall call) { 70 | FunctionSignature signature = scope.getConstructorCallSignature(call.getIdentifier(),call.getArguments()); 71 | generateArguments(call,signature); 72 | } 73 | 74 | private void generateArguments(Call call, FunctionSignature signature) { 75 | List parameters = signature.getParameters(); 76 | List arguments = call.getArguments(); 77 | if (arguments.size() > parameters.size()) { 78 | throw new BadArgumentsToFunctionCallException(call); 79 | } 80 | arguments = getSortedArguments(arguments,parameters); 81 | arguments.forEach(argument -> argument.accept(expressionGenerator)); 82 | generateDefaultParameters(call, parameters, arguments); 83 | } 84 | 85 | private List getSortedArguments(List arguments , List parameters) { 86 | Comparator argumentIndexComparator = (o1, o2) -> { 87 | if (!o1.getParameterName().isPresent()) return 0; 88 | return getIndexOfArgument(o1, parameters) - getIndexOfArgument(o2, parameters); 89 | }; 90 | return Ordering.from(argumentIndexComparator).immutableSortedCopy(arguments); 91 | } 92 | 93 | private Integer getIndexOfArgument(Argument argument, List parameters ) { 94 | String paramName = argument.getParameterName().get(); 95 | return parameters.stream() 96 | .filter(p -> p.getName().equals(paramName)) 97 | .map(parameters::indexOf) 98 | .findFirst() 99 | .orElseThrow(() -> new WrongArgumentNameException(argument, parameters)); 100 | } 101 | 102 | private void generateDefaultParameters(Call call, List parameters, List arguments) { 103 | for (int i = arguments.size(); i < parameters.size(); i++) { 104 | Expression defaultParameter = parameters.get(i).getDefaultValue() 105 | .orElseThrow(() -> new BadArgumentsToFunctionCallException(call)); 106 | defaultParameter.accept(expressionGenerator); 107 | } 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /compiler/src/main/java/com/bendcap/enkel/compiler/bytecodegenerator/expression/ConditionalExpressionGenerator.java: -------------------------------------------------------------------------------- 1 | package com.bendcap.enkel.compiler.bytecodegenerator.expression; 2 | 3 | import com.bendcap.enkel.compiler.domain.CompareSign; 4 | import com.bendcap.enkel.compiler.domain.node.expression.*; 5 | import com.bendcap.enkel.compiler.domain.scope.FunctionSignature; 6 | import com.bendcap.enkel.compiler.domain.type.BultInType; 7 | import com.bendcap.enkel.compiler.domain.type.ClassType; 8 | import org.objectweb.asm.Label; 9 | import org.objectweb.asm.MethodVisitor; 10 | import org.objectweb.asm.Opcodes; 11 | 12 | import java.util.Collections; 13 | import java.util.List; 14 | import java.util.Optional; 15 | 16 | /** 17 | * Created by KevinOfNeu on 2018/8/31 11:42. 18 | */ 19 | public class ConditionalExpressionGenerator { 20 | private final ExpressionGenerator expressionGenerator; 21 | private final MethodVisitor methodVisitor; 22 | public ConditionalExpressionGenerator(ExpressionGenerator expressionGenerator, MethodVisitor methodVisitor) { 23 | this.expressionGenerator = expressionGenerator; 24 | this.methodVisitor = methodVisitor; 25 | } 26 | public void generate(ConditionalExpression conditionalExpression) { 27 | Expression leftExpression = conditionalExpression.getLeftExpression(); 28 | Expression rightExpression = conditionalExpression.getRightExpression(); 29 | CompareSign compareSign = conditionalExpression.getCompareSign(); 30 | if (conditionalExpression.isPrimitiveComparison()) { 31 | generatePrimitivesComparison(leftExpression, rightExpression, compareSign); 32 | } else { 33 | generateObjectsComparison(leftExpression, rightExpression, compareSign); 34 | } 35 | Label endLabel = new Label(); 36 | Label trueLabel = new Label(); 37 | methodVisitor.visitJumpInsn(compareSign.getOpcode(), trueLabel); 38 | methodVisitor.visitInsn(Opcodes.ICONST_0); 39 | methodVisitor.visitJumpInsn(Opcodes.GOTO, endLabel); 40 | methodVisitor.visitLabel(trueLabel); 41 | methodVisitor.visitInsn(Opcodes.ICONST_1); 42 | methodVisitor.visitLabel(endLabel); 43 | } 44 | 45 | private void generateObjectsComparison(Expression leftExpression, Expression rightExpression, CompareSign compareSign) { 46 | Parameter parameter = new Parameter("o", new ClassType("java.lang.Object"), Optional.empty()); 47 | List parameters = Collections.singletonList(parameter); 48 | Argument argument = new Argument(rightExpression, Optional.empty()); 49 | List arguments = Collections.singletonList(argument); 50 | switch (compareSign) { 51 | case EQUAL: 52 | case NOT_EQUAL: 53 | FunctionSignature equalsSignature = new FunctionSignature("equals", parameters, BultInType.BOOLEAN); 54 | FunctionCall equalsCall = new FunctionCall(equalsSignature, arguments, leftExpression); 55 | equalsCall.accept(expressionGenerator); 56 | methodVisitor.visitInsn(Opcodes.ICONST_1); 57 | methodVisitor.visitInsn(Opcodes.IXOR); 58 | break; 59 | case LESS: 60 | case GREATER: 61 | case LESS_OR_EQUAL: 62 | case GRATER_OR_EQAL: 63 | FunctionSignature compareToSignature = new FunctionSignature("compareTo", parameters, BultInType.INT); 64 | FunctionCall compareToCall = new FunctionCall(compareToSignature, arguments, leftExpression); 65 | compareToCall.accept(expressionGenerator); 66 | break; 67 | } 68 | } 69 | 70 | private void generatePrimitivesComparison(Expression leftExpression, Expression rightExpression, CompareSign compareSign) { 71 | leftExpression.accept(expressionGenerator); 72 | rightExpression.accept(expressionGenerator); 73 | methodVisitor.visitInsn(Opcodes.ISUB); 74 | } 75 | 76 | } 77 | -------------------------------------------------------------------------------- /compiler/src/main/java/com/bendcap/enkel/compiler/bytecodegenerator/expression/ExpressionGenerator.java: -------------------------------------------------------------------------------- 1 | package com.bendcap.enkel.compiler.bytecodegenerator.expression; 2 | 3 | import com.bendcap.enkel.compiler.domain.node.expression.arthimetic.Addition; 4 | import com.bendcap.enkel.compiler.domain.node.expression.arthimetic.Division; 5 | import com.bendcap.enkel.compiler.domain.node.expression.arthimetic.Multiplication; 6 | import com.bendcap.enkel.compiler.domain.node.expression.arthimetic.Substraction; 7 | import com.bendcap.enkel.compiler.domain.node.expression.*; 8 | import com.bendcap.enkel.compiler.domain.scope.Scope; 9 | import org.objectweb.asm.MethodVisitor; 10 | 11 | /** 12 | * Created by KevinOfNeu on 2018/8/31 11:43. 13 | */ 14 | public class ExpressionGenerator { 15 | private final ReferenceExpressionGenerator referenceExpressionGenerator; 16 | private final ValueExpressionGenerator valueExpressionGenerator; 17 | private final CallExpressionGenerator callExpressionGenerator; 18 | private final ArithmeticExpressionGenerator arithmeticExpressionGenerator; 19 | private final ConditionalExpressionGenerator conditionalExpressionGenerator; 20 | private final ParameterExpressionGenerator parameterExpressionGenerator; 21 | public ExpressionGenerator(MethodVisitor methodVisitor, Scope scope) { 22 | referenceExpressionGenerator = new ReferenceExpressionGenerator(methodVisitor,scope); 23 | valueExpressionGenerator = new ValueExpressionGenerator(methodVisitor); 24 | callExpressionGenerator = new CallExpressionGenerator(this, scope, methodVisitor); 25 | arithmeticExpressionGenerator = new ArithmeticExpressionGenerator(this, methodVisitor); 26 | conditionalExpressionGenerator = new ConditionalExpressionGenerator(this, methodVisitor); 27 | parameterExpressionGenerator = new ParameterExpressionGenerator(methodVisitor, scope); 28 | } 29 | public void generate(FieldReference fieldReference) { 30 | referenceExpressionGenerator.generate(fieldReference); 31 | } 32 | public void generate(LocalVariableReference reference) { 33 | referenceExpressionGenerator.generate(reference); 34 | } 35 | public void generate(Parameter parameter) { 36 | parameterExpressionGenerator.generate(parameter); 37 | } 38 | public void generate(Value value) { 39 | valueExpressionGenerator.generate(value); 40 | } 41 | public void generate(ConstructorCall constructorCall) { 42 | callExpressionGenerator.generate(constructorCall); 43 | } 44 | public void generate(SuperCall superCall) { 45 | callExpressionGenerator.generate(superCall); 46 | } 47 | public void generate(FunctionCall functionCall) { 48 | callExpressionGenerator.generate(functionCall); 49 | } 50 | public void generate(Addition expression) { 51 | arithmeticExpressionGenerator.generate(expression); 52 | } 53 | public void generate(Substraction expression) { 54 | arithmeticExpressionGenerator.generate(expression); 55 | } 56 | public void generate(Multiplication expression) { 57 | arithmeticExpressionGenerator.generate(expression); 58 | } 59 | public void generate(Division expression) { 60 | arithmeticExpressionGenerator.generate(expression); 61 | } 62 | public void generate(ConditionalExpression conditionalExpression) { 63 | conditionalExpressionGenerator.generate(conditionalExpression); 64 | } 65 | public void generate(EmptyExpression emptyExpression) { 66 | //do nothing ;) 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /compiler/src/main/java/com/bendcap/enkel/compiler/bytecodegenerator/expression/ParameterExpressionGenerator.java: -------------------------------------------------------------------------------- 1 | package com.bendcap.enkel.compiler.bytecodegenerator.expression; 2 | 3 | import com.bendcap.enkel.compiler.domain.node.expression.Parameter; 4 | import com.bendcap.enkel.compiler.domain.scope.Scope; 5 | import com.bendcap.enkel.compiler.domain.type.Type; 6 | import org.objectweb.asm.MethodVisitor; 7 | 8 | /** 9 | * Created by KevinOfNeu on 2018/8/31 11:44. 10 | */ 11 | public class ParameterExpressionGenerator { 12 | private final MethodVisitor methodVisitor; 13 | private final Scope scope; 14 | public ParameterExpressionGenerator(MethodVisitor methodVisitor, Scope scope) { 15 | this.methodVisitor = methodVisitor; 16 | this.scope = scope; 17 | } 18 | public void generate(Parameter parameter) { 19 | Type type = parameter.getType(); 20 | int index = scope.getLocalVariableIndex(parameter.getName()); 21 | methodVisitor.visitVarInsn(type.getLoadVariableOpcode(), index); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /compiler/src/main/java/com/bendcap/enkel/compiler/bytecodegenerator/expression/ReferenceExpressionGenerator.java: -------------------------------------------------------------------------------- 1 | package com.bendcap.enkel.compiler.bytecodegenerator.expression; 2 | 3 | import com.bendcap.enkel.compiler.domain.node.expression.FieldReference; 4 | import com.bendcap.enkel.compiler.domain.node.expression.LocalVariableReference; 5 | import com.bendcap.enkel.compiler.domain.scope.Scope; 6 | import com.bendcap.enkel.compiler.domain.type.Type; 7 | import org.objectweb.asm.MethodVisitor; 8 | import org.objectweb.asm.Opcodes; 9 | 10 | /** 11 | * Created by KevinOfNeu on 2018/8/31 23:15. 12 | */ 13 | public class ReferenceExpressionGenerator { 14 | private final MethodVisitor methodVisitor; 15 | private final Scope scope; 16 | public ReferenceExpressionGenerator(MethodVisitor methodVisitor, Scope scope) { 17 | this.methodVisitor = methodVisitor; 18 | this.scope = scope; 19 | } 20 | public void generate(LocalVariableReference localVariableReference) { 21 | String varName = localVariableReference.geName(); 22 | int index = scope.getLocalVariableIndex(varName); 23 | Type type = localVariableReference.getType(); 24 | methodVisitor.visitVarInsn(type.getLoadVariableOpcode(), index); 25 | } 26 | public void generate(FieldReference fieldReference) { 27 | String varName = fieldReference.geName(); 28 | Type type = fieldReference.getType(); 29 | String ownerInternalName = fieldReference.getOwnerInternalName(); 30 | String descriptor = type.getDescriptor(); 31 | methodVisitor.visitVarInsn(Opcodes.ALOAD,0); 32 | methodVisitor.visitFieldInsn(Opcodes.GETFIELD, ownerInternalName,varName,descriptor); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /compiler/src/main/java/com/bendcap/enkel/compiler/bytecodegenerator/expression/ValueExpressionGenerator.java: -------------------------------------------------------------------------------- 1 | package com.bendcap.enkel.compiler.bytecodegenerator.expression; 2 | 3 | import com.bendcap.enkel.compiler.domain.node.expression.Value; 4 | import com.bendcap.enkel.compiler.domain.type.Type; 5 | import com.bendcap.enkel.compiler.utils.TypeResolver; 6 | import org.objectweb.asm.MethodVisitor; 7 | 8 | /** 9 | * Created by KevinOfNeu on 2018/8/31 11:45. 10 | */ 11 | public class ValueExpressionGenerator { 12 | private final MethodVisitor methodVisitor; 13 | public ValueExpressionGenerator(MethodVisitor methodVisitor) { 14 | this.methodVisitor = methodVisitor; 15 | } 16 | public void generate(Value value) { 17 | Type type = value.getType(); 18 | String stringValue = value.getValue(); 19 | Object transformedValue = TypeResolver.getValueFromString(stringValue, type); 20 | methodVisitor.visitLdcInsn(transformedValue); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /compiler/src/main/java/com/bendcap/enkel/compiler/bytecodegenerator/statement/AssignmentStatementGenerator.java: -------------------------------------------------------------------------------- 1 | package com.bendcap.enkel.compiler.bytecodegenerator.statement; 2 | 3 | import com.bendcap.enkel.compiler.bytecodegenerator.expression.ExpressionGenerator; 4 | import com.bendcap.enkel.compiler.domain.node.expression.Expression; 5 | import com.bendcap.enkel.compiler.domain.node.statement.Assignment; 6 | import com.bendcap.enkel.compiler.domain.scope.Field; 7 | import com.bendcap.enkel.compiler.domain.scope.LocalVariable; 8 | import com.bendcap.enkel.compiler.domain.scope.Scope; 9 | import com.bendcap.enkel.compiler.domain.type.Type; 10 | import org.objectweb.asm.MethodVisitor; 11 | import org.objectweb.asm.Opcodes; 12 | 13 | /** 14 | * Created by KevinOfNeu on 2018/8/31 11:45. 15 | */ 16 | public class AssignmentStatementGenerator { 17 | private final MethodVisitor methodVisitor; 18 | private final ExpressionGenerator expressionGenerator; 19 | private final Scope scope; 20 | public AssignmentStatementGenerator(MethodVisitor methodVisitor, ExpressionGenerator expressionGenerator, Scope scope) { 21 | this.methodVisitor = methodVisitor; 22 | this.expressionGenerator = expressionGenerator; 23 | this.scope = scope; 24 | } 25 | public void generate(Assignment assignment) { 26 | String varName = assignment.getVarName(); 27 | Expression expression = assignment.getExpression(); 28 | Type type = expression.getType(); 29 | if(scope.isLocalVariableExists(varName)) { 30 | int index = scope.getLocalVariableIndex(varName); 31 | LocalVariable localVariable = scope.getLocalVariable(varName); 32 | Type localVariableType = localVariable.getType(); 33 | castIfNecessary(type, localVariableType); 34 | methodVisitor.visitVarInsn(type.getStoreVariableOpcode(), index); 35 | return; 36 | } 37 | Field field = scope.getField(varName); 38 | String descriptor = field.getType().getDescriptor(); 39 | methodVisitor.visitVarInsn(Opcodes.ALOAD,0); 40 | expression.accept(expressionGenerator); 41 | castIfNecessary(type, field.getType()); 42 | methodVisitor.visitFieldInsn(Opcodes.PUTFIELD,field.getOwnerInternalName(),field.getName(),descriptor); 43 | } 44 | 45 | public void castIfNecessary(Type expressionType, Type variableType) { 46 | if (!expressionType.equals(variableType)) { 47 | methodVisitor.visitTypeInsn(Opcodes.CHECKCAST, variableType.getInternalName()); 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /compiler/src/main/java/com/bendcap/enkel/compiler/bytecodegenerator/statement/BlockStatementGenerator.java: -------------------------------------------------------------------------------- 1 | package com.bendcap.enkel.compiler.bytecodegenerator.statement; 2 | 3 | import com.bendcap.enkel.compiler.domain.node.statement.Block; 4 | import com.bendcap.enkel.compiler.domain.node.statement.Statement; 5 | import com.bendcap.enkel.compiler.domain.scope.Scope; 6 | import org.objectweb.asm.MethodVisitor; 7 | 8 | import java.util.List; 9 | 10 | /** 11 | * Created by KevinOfNeu on 2018/8/31 11:46. 12 | */ 13 | public class BlockStatementGenerator { 14 | private final MethodVisitor methodVisitor; 15 | public BlockStatementGenerator(MethodVisitor methodVisitor) { 16 | this.methodVisitor = methodVisitor; 17 | } 18 | public void generate(Block block) { 19 | Scope newScope = block.getScope(); 20 | List statements = block.getStatements(); 21 | StatementGenerator statementGenerator = new StatementGenerator(methodVisitor, newScope); 22 | statements.stream().forEach(stmt -> stmt.accept(statementGenerator)); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /compiler/src/main/java/com/bendcap/enkel/compiler/bytecodegenerator/statement/ForStatementGenerator.java: -------------------------------------------------------------------------------- 1 | package com.bendcap.enkel.compiler.bytecodegenerator.statement; 2 | 3 | import com.bendcap.enkel.compiler.bytecodegenerator.expression.ExpressionGenerator; 4 | import com.bendcap.enkel.compiler.domain.CompareSign; 5 | import com.bendcap.enkel.compiler.domain.node.expression.ConditionalExpression; 6 | import com.bendcap.enkel.compiler.domain.node.expression.Expression; 7 | import com.bendcap.enkel.compiler.domain.node.expression.FieldReference; 8 | import com.bendcap.enkel.compiler.domain.node.expression.LocalVariableReference; 9 | import com.bendcap.enkel.compiler.domain.node.statement.RangedForStatement; 10 | import com.bendcap.enkel.compiler.domain.node.statement.Statement; 11 | import com.bendcap.enkel.compiler.domain.scope.LocalVariable; 12 | import com.bendcap.enkel.compiler.domain.scope.Scope; 13 | import org.objectweb.asm.Label; 14 | import org.objectweb.asm.MethodVisitor; 15 | import org.objectweb.asm.Opcodes; 16 | 17 | /** 18 | * Created by KevinOfNeu on 2018/8/31 11:46. 19 | */ 20 | public class ForStatementGenerator { 21 | private final MethodVisitor methodVisitor; 22 | public ForStatementGenerator(MethodVisitor methodVisitor) { 23 | this.methodVisitor = methodVisitor; 24 | } 25 | public void generate(RangedForStatement rangedForStatement) { 26 | Scope newScope = rangedForStatement.getScope(); 27 | StatementGenerator scopeGeneratorWithNewScope = new StatementGenerator(methodVisitor, newScope); 28 | ExpressionGenerator exprGeneratorWithNewScope = new ExpressionGenerator(methodVisitor, newScope); 29 | Statement iterator = rangedForStatement.getIteratorVariableStatement(); 30 | Label incrementationSection = new Label(); 31 | Label decrementationSection = new Label(); 32 | Label endLoopSection = new Label(); 33 | String iteratorVarName = rangedForStatement.getIteratorVarName(); 34 | Expression endExpression = rangedForStatement.getEndExpression(); 35 | LocalVariable variable = new LocalVariable(iteratorVarName,rangedForStatement.getType()); 36 | Expression iteratorVariable = new LocalVariableReference(variable); 37 | ConditionalExpression iteratorGreaterThanEndConditional = new ConditionalExpression(iteratorVariable, endExpression, CompareSign.GREATER); 38 | ConditionalExpression iteratorLessThanEndConditional = new ConditionalExpression(iteratorVariable, endExpression, CompareSign.LESS); 39 | iterator.accept(scopeGeneratorWithNewScope); 40 | iteratorLessThanEndConditional.accept(exprGeneratorWithNewScope); 41 | methodVisitor.visitJumpInsn(Opcodes.IFNE, incrementationSection); 42 | iteratorGreaterThanEndConditional.accept(exprGeneratorWithNewScope); 43 | methodVisitor.visitJumpInsn(Opcodes.IFNE, decrementationSection); 44 | methodVisitor.visitLabel(incrementationSection); 45 | rangedForStatement.getStatement().accept(scopeGeneratorWithNewScope); 46 | methodVisitor.visitIincInsn(newScope.getLocalVariableIndex(iteratorVarName), 1); 47 | iteratorGreaterThanEndConditional.accept(exprGeneratorWithNewScope); 48 | methodVisitor.visitJumpInsn(Opcodes.IFEQ, incrementationSection); 49 | methodVisitor.visitJumpInsn(Opcodes.GOTO, endLoopSection); 50 | methodVisitor.visitLabel(decrementationSection); 51 | rangedForStatement.getStatement().accept(scopeGeneratorWithNewScope); 52 | methodVisitor.visitIincInsn(newScope.getLocalVariableIndex(iteratorVarName), -1); 53 | iteratorLessThanEndConditional.accept(exprGeneratorWithNewScope); 54 | methodVisitor.visitJumpInsn(Opcodes.IFEQ, decrementationSection); 55 | methodVisitor.visitLabel(endLoopSection); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /compiler/src/main/java/com/bendcap/enkel/compiler/bytecodegenerator/statement/IfStatementGenerator.java: -------------------------------------------------------------------------------- 1 | package com.bendcap.enkel.compiler.bytecodegenerator.statement; 2 | 3 | import com.bendcap.enkel.compiler.bytecodegenerator.expression.ExpressionGenerator; 4 | import com.bendcap.enkel.compiler.domain.node.expression.Expression; 5 | import com.bendcap.enkel.compiler.domain.node.statement.IfStatement; 6 | import com.bendcap.enkel.compiler.domain.node.statement.Statement; 7 | import org.objectweb.asm.Label; 8 | import org.objectweb.asm.MethodVisitor; 9 | import org.objectweb.asm.Opcodes; 10 | 11 | import java.util.Optional; 12 | 13 | /** 14 | * Created by KevinOfNeu on 2018/8/31 11:46. 15 | */ 16 | public class IfStatementGenerator { 17 | private final StatementGenerator statementGenerator; 18 | private final ExpressionGenerator expressionGenerator; 19 | private final MethodVisitor methodVisitor; 20 | public IfStatementGenerator(StatementGenerator statementGenerator, ExpressionGenerator expressionGenerator, MethodVisitor methodVisitor) { 21 | this.statementGenerator = statementGenerator; 22 | this.expressionGenerator = expressionGenerator; 23 | this.methodVisitor = methodVisitor; 24 | } 25 | public void generate(IfStatement ifStatement) { 26 | Expression condition = ifStatement.getCondition(); 27 | condition.accept(expressionGenerator); 28 | Label trueLabel = new Label(); 29 | Label endLabel = new Label(); 30 | methodVisitor.visitJumpInsn(Opcodes.IFNE, trueLabel); 31 | Optional falseStatement = ifStatement.getFalseStatement(); 32 | if (falseStatement.isPresent()) { 33 | falseStatement.get().accept(statementGenerator); 34 | } 35 | methodVisitor.visitJumpInsn(Opcodes.GOTO, endLabel); 36 | methodVisitor.visitLabel(trueLabel); 37 | ifStatement.getTrueStatement().accept(statementGenerator); 38 | methodVisitor.visitLabel(endLabel); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /compiler/src/main/java/com/bendcap/enkel/compiler/bytecodegenerator/statement/PrintStatementGenerator.java: -------------------------------------------------------------------------------- 1 | package com.bendcap.enkel.compiler.bytecodegenerator.statement; 2 | 3 | import com.bendcap.enkel.compiler.bytecodegenerator.expression.ExpressionGenerator; 4 | import com.bendcap.enkel.compiler.domain.node.expression.Expression; 5 | import com.bendcap.enkel.compiler.domain.node.statement.PrintStatement; 6 | import com.bendcap.enkel.compiler.domain.type.ClassType; 7 | import com.bendcap.enkel.compiler.domain.type.Type; 8 | import org.objectweb.asm.MethodVisitor; 9 | import org.objectweb.asm.Opcodes; 10 | 11 | /** 12 | * Created by KevinOfNeu on 2018/8/31 11:47. 13 | */ 14 | public class PrintStatementGenerator { 15 | private final MethodVisitor methodVisitor; 16 | private final ExpressionGenerator expressionGenerator; 17 | public PrintStatementGenerator(ExpressionGenerator expressionGenerator, MethodVisitor methodVisitor) { 18 | this.methodVisitor = methodVisitor; 19 | this.expressionGenerator = expressionGenerator; 20 | } 21 | public void generate(PrintStatement printStatement) { 22 | Expression expression = printStatement.getExpression(); 23 | methodVisitor.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;"); 24 | expression.accept(expressionGenerator); 25 | Type type = expression.getType(); 26 | String descriptor = "(" + type.getDescriptor() + ")V"; 27 | ClassType owner = new ClassType("java.io.PrintStream"); 28 | String fieldDescriptor = owner.getDescriptor(); 29 | methodVisitor.visitMethodInsn(Opcodes.INVOKEVIRTUAL, fieldDescriptor, "println", descriptor, false); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /compiler/src/main/java/com/bendcap/enkel/compiler/bytecodegenerator/statement/ReturnStatemenetGenerator.java: -------------------------------------------------------------------------------- 1 | package com.bendcap.enkel.compiler.bytecodegenerator.statement; 2 | 3 | import com.bendcap.enkel.compiler.bytecodegenerator.expression.ExpressionGenerator; 4 | import com.bendcap.enkel.compiler.domain.node.expression.Expression; 5 | import com.bendcap.enkel.compiler.domain.node.statement.ReturnStatement; 6 | import com.bendcap.enkel.compiler.domain.type.Type; 7 | import org.objectweb.asm.MethodVisitor; 8 | 9 | /** 10 | * Created by KevinOfNeu on 2018/8/31 11:47. 11 | */ 12 | public class ReturnStatemenetGenerator { 13 | private final ExpressionGenerator expressionGenerator; 14 | private final MethodVisitor methodVisitor; 15 | public ReturnStatemenetGenerator(ExpressionGenerator expressionGenerator, MethodVisitor methodVisitor) { 16 | this.expressionGenerator = expressionGenerator; 17 | this.methodVisitor = methodVisitor; 18 | } 19 | public void generate(ReturnStatement returnStatement) { 20 | Expression expression = returnStatement.getExpression(); 21 | Type type = expression.getType(); 22 | expression.accept(expressionGenerator); 23 | methodVisitor.visitInsn(type.getReturnOpcode()); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /compiler/src/main/java/com/bendcap/enkel/compiler/bytecodegenerator/statement/StatementGenerator.java: -------------------------------------------------------------------------------- 1 | package com.bendcap.enkel.compiler.bytecodegenerator.statement; 2 | 3 | import com.bendcap.enkel.compiler.bytecodegenerator.expression.ExpressionGenerator; 4 | import com.bendcap.enkel.compiler.domain.node.expression.arthimetic.Addition; 5 | import com.bendcap.enkel.compiler.domain.node.expression.arthimetic.Division; 6 | import com.bendcap.enkel.compiler.domain.node.expression.arthimetic.Multiplication; 7 | import com.bendcap.enkel.compiler.domain.node.expression.arthimetic.Substraction; 8 | import com.bendcap.enkel.compiler.domain.node.expression.*; 9 | import com.bendcap.enkel.compiler.domain.node.statement.*; 10 | import com.bendcap.enkel.compiler.domain.scope.Scope; 11 | import org.objectweb.asm.MethodVisitor; 12 | 13 | /** 14 | * Created by KevinOfNeu on 2018/8/31 11:47. 15 | */ 16 | public class StatementGenerator { 17 | private final PrintStatementGenerator printStatementGenerator; 18 | private final VariableDeclarationStatementGenerator variableDeclarationStatementGenerator; 19 | private final ReturnStatemenetGenerator returnStatemenetGenerator; 20 | private final IfStatementGenerator ifStatementGenerator; 21 | private final BlockStatementGenerator blockStatementGenerator; 22 | private final ForStatementGenerator forStatementGenerator; 23 | private final AssignmentStatementGenerator assignmentStatementGenerator; 24 | private final ExpressionGenerator expressionGenerator; 25 | public StatementGenerator(MethodVisitor methodVisitor, Scope scope) { 26 | expressionGenerator = new ExpressionGenerator(methodVisitor, scope); 27 | printStatementGenerator = new PrintStatementGenerator(expressionGenerator,methodVisitor); 28 | variableDeclarationStatementGenerator = new VariableDeclarationStatementGenerator(this, expressionGenerator); 29 | forStatementGenerator = new ForStatementGenerator(methodVisitor); 30 | blockStatementGenerator = new BlockStatementGenerator(methodVisitor); 31 | ifStatementGenerator = new IfStatementGenerator(this, expressionGenerator, methodVisitor); 32 | returnStatemenetGenerator = new ReturnStatemenetGenerator(expressionGenerator, methodVisitor); 33 | assignmentStatementGenerator = new AssignmentStatementGenerator(methodVisitor, expressionGenerator, scope); 34 | } 35 | public void generate(PrintStatement printStatement) { 36 | printStatementGenerator.generate(printStatement); 37 | } 38 | public void generate(VariableDeclaration variableDeclaration) { 39 | variableDeclarationStatementGenerator.generate(variableDeclaration); 40 | } 41 | public void generate(FunctionCall functionCall) { 42 | functionCall.accept(expressionGenerator); 43 | } 44 | public void generate(ReturnStatement returnStatement) { 45 | returnStatemenetGenerator.generate(returnStatement); 46 | } 47 | public void generate(IfStatement ifStatement) { 48 | ifStatementGenerator.generate(ifStatement); 49 | } 50 | public void generate(Block block) { 51 | blockStatementGenerator.generate(block); 52 | } 53 | public void generate(RangedForStatement rangedForStatement) { 54 | forStatementGenerator.generate(rangedForStatement); 55 | } 56 | public void generate(Assignment assignment) { 57 | assignmentStatementGenerator.generate(assignment); 58 | } 59 | public void generate(SuperCall superCall) { 60 | expressionGenerator.generate(superCall); 61 | } 62 | public void generate(ConstructorCall constructorCall) { 63 | expressionGenerator.generate(constructorCall); 64 | } 65 | public void generate(Addition addition) { 66 | expressionGenerator.generate(addition); 67 | } 68 | public void generate(Parameter parameter) { 69 | expressionGenerator.generate(parameter); 70 | } 71 | public void generate(ConditionalExpression conditionalExpression) { 72 | expressionGenerator.generate(conditionalExpression); 73 | } 74 | public void generate(Multiplication multiplication) { 75 | expressionGenerator.generate(multiplication); 76 | } 77 | public void generate(Value value) { 78 | expressionGenerator.generate(value); 79 | } 80 | 81 | public void generate(Substraction substraction) { 82 | expressionGenerator.generate(substraction); 83 | } 84 | public void generate(Division division) { 85 | expressionGenerator.generate(division); 86 | } 87 | public void generate(EmptyExpression emptyExpression) { 88 | expressionGenerator.generate(emptyExpression); 89 | } 90 | 91 | public void generate(LocalVariableReference localVariableReference) { 92 | expressionGenerator.generate(localVariableReference); 93 | } 94 | public void generate(FieldReference fieldReference) { 95 | expressionGenerator.generate(fieldReference); 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /compiler/src/main/java/com/bendcap/enkel/compiler/bytecodegenerator/statement/VariableDeclarationStatementGenerator.java: -------------------------------------------------------------------------------- 1 | package com.bendcap.enkel.compiler.bytecodegenerator.statement; 2 | 3 | import com.bendcap.enkel.compiler.bytecodegenerator.expression.ExpressionGenerator; 4 | import com.bendcap.enkel.compiler.domain.node.expression.Expression; 5 | import com.bendcap.enkel.compiler.domain.node.statement.Assignment; 6 | import com.bendcap.enkel.compiler.domain.node.statement.VariableDeclaration; 7 | 8 | /** 9 | * Created by KevinOfNeu on 2018/8/31 11:48. 10 | */ 11 | public class VariableDeclarationStatementGenerator { 12 | private final StatementGenerator statementGenerator; 13 | private final ExpressionGenerator expressionGenerator; 14 | public VariableDeclarationStatementGenerator(StatementGenerator statementGenerator, ExpressionGenerator expressionGenerator) { 15 | this.statementGenerator = statementGenerator; 16 | this.expressionGenerator = expressionGenerator; 17 | } 18 | public void generate(VariableDeclaration variableDeclaration) { 19 | Expression expression = variableDeclaration.getExpression(); 20 | expression.accept(expressionGenerator); 21 | Assignment assignment = new Assignment(variableDeclaration); 22 | assignment.accept(statementGenerator); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /compiler/src/main/java/com/bendcap/enkel/compiler/compiler/Compiler.java: -------------------------------------------------------------------------------- 1 | package com.bendcap.enkel.compiler.compiler; 2 | 3 | import com.bendcap.enkel.compiler.domain.CompilationUnit; 4 | import com.bendcap.enkel.compiler.bytecodegenerator.BytecodeGenerator; 5 | import com.bendcap.enkel.compiler.parsing.Parser; 6 | import com.bendcap.enkel.compiler.validation.ARGUMENT_ERRORS; 7 | import org.apache.commons.io.IOUtils; 8 | 9 | import java.io.File; 10 | import java.io.FileOutputStream; 11 | import java.io.IOException; 12 | import java.io.OutputStream; 13 | 14 | /** 15 | * Created by KevinOfNeu on 2018/7/18 21:14. 16 | */ 17 | public class Compiler { 18 | 19 | public static void main(String[] args) { 20 | try { 21 | new Compiler().compile(args); 22 | } catch (Exception e) { 23 | e.printStackTrace(); 24 | } 25 | } 26 | 27 | public void compile(String[] args) throws Exception { 28 | final ARGUMENT_ERRORS argumentsErrors = getArgumentValidationErrors(args); 29 | if (argumentsErrors != ARGUMENT_ERRORS.NONE) { 30 | System.out.println(argumentsErrors.getMessage()); 31 | return; 32 | } 33 | final File enkelFile = new File(args[0]); 34 | String fileAbsolutePath = enkelFile.getAbsolutePath(); 35 | final CompilationUnit compilationUnit = new Parser().getCompilationUnit(fileAbsolutePath); 36 | saveBytecodeToClassFile(compilationUnit); 37 | } 38 | 39 | private ARGUMENT_ERRORS getArgumentValidationErrors(String[] args) { 40 | if (args.length != 1) { 41 | return ARGUMENT_ERRORS.NO_FILE; 42 | } 43 | String filePath = args[0]; 44 | if (!filePath.endsWith(".enk")) { 45 | return ARGUMENT_ERRORS.BAD_FILE_EXTENSION; 46 | } 47 | return ARGUMENT_ERRORS.NONE; 48 | } 49 | 50 | private static void saveBytecodeToClassFile(CompilationUnit compilationUnit) throws IOException { 51 | BytecodeGenerator bytecodeGenerator = new BytecodeGenerator(); 52 | final byte[] byteCode = bytecodeGenerator.generate(compilationUnit); 53 | String className = compilationUnit.getClassName(); 54 | String fileName = className + ".class"; 55 | OutputStream os = new FileOutputStream(fileName); 56 | IOUtils.write(byteCode, os); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /compiler/src/main/java/com/bendcap/enkel/compiler/domain/ClassDeclaration.java: -------------------------------------------------------------------------------- 1 | package com.bendcap.enkel.compiler.domain; 2 | 3 | import com.bendcap.enkel.compiler.domain.scope.Field; 4 | 5 | import java.util.Collections; 6 | import java.util.List; 7 | 8 | /** 9 | * Created by KevinOfNeu on 2018/8/22 10:08. 10 | */ 11 | public class ClassDeclaration { 12 | private String name; 13 | private List fields; 14 | private List methods; 15 | 16 | public ClassDeclaration(String name, List fields, List methods) { 17 | this.name = name; 18 | this.fields = fields; 19 | this.methods = methods; 20 | } 21 | 22 | public String getName() { 23 | return name; 24 | } 25 | 26 | public List getFields() { 27 | return Collections.unmodifiableList(fields); 28 | } 29 | 30 | public List getMethods() { 31 | return Collections.unmodifiableList(methods); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /compiler/src/main/java/com/bendcap/enkel/compiler/domain/CompareSign.java: -------------------------------------------------------------------------------- 1 | package com.bendcap.enkel.compiler.domain; 2 | 3 | import org.objectweb.asm.Opcodes; 4 | 5 | import java.util.Arrays; 6 | 7 | /** 8 | * Created by KevinOfNeu on 2018/8/24 22:54. 9 | */ 10 | public enum CompareSign { 11 | EQUAL("==", Opcodes.IFEQ), 12 | NOT_EQUAL("!=", Opcodes.IFNE), 13 | LESS("<",Opcodes.IFLT), 14 | GREATER(">",Opcodes.IFGT), 15 | LESS_OR_EQUAL("<=",Opcodes.IFLE), 16 | GRATER_OR_EQAL(">=",Opcodes.IFGE); 17 | 18 | private String sign; 19 | //reversed. '>' evalutes to le -> less or equal 20 | private int opcode; 21 | 22 | CompareSign(String s, int opcode) { 23 | sign = s; 24 | this.opcode = opcode; 25 | } 26 | 27 | public int getOpcode() { 28 | return opcode; 29 | } 30 | 31 | public static CompareSign fromString(String sign) { 32 | return Arrays.stream(values()).filter(cmpSign -> cmpSign.sign.equals(sign)) 33 | .findFirst() 34 | .orElseThrow(() -> new RuntimeException("Sign not implemented")); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /compiler/src/main/java/com/bendcap/enkel/compiler/domain/CompilationUnit.java: -------------------------------------------------------------------------------- 1 | package com.bendcap.enkel.compiler.domain; 2 | 3 | /** 4 | * Created by KevinOfNeu on 2018/8/22 10:08. 5 | */ 6 | public class CompilationUnit { 7 | private ClassDeclaration classDeclaration; 8 | 9 | public CompilationUnit(ClassDeclaration classDeclaration) { 10 | this.classDeclaration = classDeclaration; 11 | } 12 | 13 | 14 | public ClassDeclaration getClassDeclaration() { 15 | return classDeclaration; 16 | } 17 | 18 | 19 | public String getClassName() { 20 | return classDeclaration.getName(); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /compiler/src/main/java/com/bendcap/enkel/compiler/domain/Constructor.java: -------------------------------------------------------------------------------- 1 | package com.bendcap.enkel.compiler.domain; 2 | 3 | import com.bendcap.enkel.compiler.bytecodegenerator.MethodGenerator; 4 | import com.bendcap.enkel.compiler.domain.scope.FunctionSignature; 5 | import com.bendcap.enkel.compiler.domain.node.statement.Statement; 6 | import com.bendcap.enkel.compiler.domain.type.BultInType; 7 | import com.bendcap.enkel.compiler.domain.type.Type; 8 | 9 | /** 10 | * Created by KevinOfNeu on 2018/8/30 16:02. 11 | */ 12 | public class Constructor extends Function { 13 | public Constructor(FunctionSignature functionSignature, Statement block) { 14 | super(functionSignature, block); 15 | } 16 | 17 | @Override 18 | public Type getReturnType() { 19 | return BultInType.VOID; 20 | } 21 | 22 | @Override 23 | public void accept(MethodGenerator generator) { 24 | generator.generate(this); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /compiler/src/main/java/com/bendcap/enkel/compiler/domain/Function.java: -------------------------------------------------------------------------------- 1 | package com.bendcap.enkel.compiler.domain; 2 | 3 | import com.bendcap.enkel.compiler.bytecodegenerator.MethodGenerator; 4 | import com.bendcap.enkel.compiler.domain.node.expression.Parameter; 5 | import com.bendcap.enkel.compiler.domain.scope.FunctionSignature; 6 | import com.bendcap.enkel.compiler.domain.node.statement.Statement; 7 | import com.bendcap.enkel.compiler.domain.type.Type; 8 | 9 | import java.util.Collections; 10 | import java.util.List; 11 | 12 | /** 13 | * Created by KevinOfNeu on 2018/8/22 09:25. 14 | */ 15 | public class Function { 16 | private FunctionSignature functionSignature; 17 | private Statement rootStatement; 18 | 19 | public Function(FunctionSignature functionSignature, Statement rootStatement) { 20 | this.functionSignature = functionSignature; 21 | this.rootStatement = rootStatement; 22 | } 23 | 24 | public String getName() { 25 | return functionSignature.getName(); 26 | } 27 | 28 | public List getParameters() { 29 | return Collections.unmodifiableList(functionSignature.getParameters()); 30 | } 31 | 32 | public Statement getRootStatement() { 33 | return rootStatement; 34 | } 35 | 36 | public Type getReturnType() { 37 | return functionSignature.getReturnType(); 38 | } 39 | 40 | public void accept(MethodGenerator generator) { 41 | generator.generate(this); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /compiler/src/main/java/com/bendcap/enkel/compiler/domain/MetaData.java: -------------------------------------------------------------------------------- 1 | package com.bendcap.enkel.compiler.domain; 2 | 3 | /** 4 | * Created by KevinOfNeu on 2018/8/22 09:41. 5 | */ 6 | public class MetaData { 7 | private String className; 8 | private String superClassName; 9 | 10 | public MetaData(String className, String superClassName) { 11 | this.className = className; 12 | this.superClassName = superClassName; 13 | } 14 | 15 | public String getClassName() { 16 | return className; 17 | } 18 | 19 | public String getSuperClassName() { 20 | return superClassName; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /compiler/src/main/java/com/bendcap/enkel/compiler/domain/node/Node.java: -------------------------------------------------------------------------------- 1 | package com.bendcap.enkel.compiler.domain.node; 2 | 3 | /** 4 | * Created by KevinOfNeu on 2018/8/23 16:29. 5 | */ 6 | public interface Node { 7 | } 8 | -------------------------------------------------------------------------------- /compiler/src/main/java/com/bendcap/enkel/compiler/domain/node/expression/Argument.java: -------------------------------------------------------------------------------- 1 | package com.bendcap.enkel.compiler.domain.node.expression; 2 | 3 | import com.bendcap.enkel.compiler.bytecodegenerator.expression.ExpressionGenerator; 4 | import com.bendcap.enkel.compiler.bytecodegenerator.statement.StatementGenerator; 5 | import com.bendcap.enkel.compiler.domain.type.Type; 6 | 7 | import java.util.Optional; 8 | 9 | /** 10 | * Created by KevinOfNeu on 2018/8/31 11:53. 11 | */ 12 | public class Argument implements Expression { 13 | private final Optional parameterName; 14 | private final Expression expression; 15 | public Argument(Expression expression, Optional parameterName) { 16 | this.parameterName = parameterName; 17 | this.expression = expression; 18 | } 19 | @Override 20 | public Type getType() { 21 | return expression.getType(); 22 | } 23 | @Override 24 | public void accept(ExpressionGenerator genrator) { 25 | expression.accept(genrator); 26 | } 27 | @Override 28 | public void accept(StatementGenerator generator) { 29 | expression.accept(generator); 30 | } 31 | public Optional getParameterName() { 32 | return parameterName; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /compiler/src/main/java/com/bendcap/enkel/compiler/domain/node/expression/Call.java: -------------------------------------------------------------------------------- 1 | package com.bendcap.enkel.compiler.domain.node.expression; 2 | 3 | import java.util.List; 4 | 5 | /** 6 | * Created by KevinOfNeu on 2018/8/30 15:31. 7 | */ 8 | public interface Call extends Expression { 9 | List getArguments(); 10 | 11 | String getIdentifier(); 12 | } 13 | -------------------------------------------------------------------------------- /compiler/src/main/java/com/bendcap/enkel/compiler/domain/node/expression/ConditionalExpression.java: -------------------------------------------------------------------------------- 1 | package com.bendcap.enkel.compiler.domain.node.expression; 2 | 3 | import com.bendcap.enkel.compiler.bytecodegenerator.expression.ExpressionGenerator; 4 | import com.bendcap.enkel.compiler.bytecodegenerator.statement.StatementGenerator; 5 | import com.bendcap.enkel.compiler.domain.CompareSign; 6 | import com.bendcap.enkel.compiler.domain.type.BultInType; 7 | import com.bendcap.enkel.compiler.domain.type.Type; 8 | import com.bendcap.enkel.compiler.exception.MixedComparisonNotAllowedException; 9 | 10 | /** 11 | * Created by KevinOfNeu on 2018/8/24 22:56. 12 | */ 13 | public class ConditionalExpression implements Expression { 14 | 15 | private CompareSign compareSign; 16 | private Expression leftExpression; 17 | private Expression rightExpression; 18 | private Type type; 19 | private boolean isPrimitiveComparison; 20 | 21 | public ConditionalExpression(Expression leftExpression, Expression rightExpression, CompareSign compareSign) { 22 | this.type = BultInType.BOOLEAN; 23 | this.compareSign = compareSign; 24 | this.leftExpression = leftExpression; 25 | this.rightExpression = rightExpression; 26 | boolean leftExpressionIsPrimitive = leftExpression.getType().getTypeClass().isPrimitive(); 27 | boolean rightExpressionIsPrimitive = rightExpression.getType().getTypeClass().isPrimitive(); 28 | isPrimitiveComparison = leftExpressionIsPrimitive && rightExpressionIsPrimitive; 29 | boolean isObjectsComparison = !leftExpressionIsPrimitive && !rightExpressionIsPrimitive; 30 | boolean isMixedComparison = !isPrimitiveComparison && !isObjectsComparison; 31 | if (isMixedComparison) { 32 | throw new MixedComparisonNotAllowedException(leftExpression.getType(), rightExpression.getType()); 33 | } 34 | } 35 | 36 | 37 | public CompareSign getCompareSign() { 38 | return compareSign; 39 | } 40 | 41 | public Expression getLeftExpression() { 42 | return leftExpression; 43 | } 44 | 45 | public Expression getRightExpression() { 46 | return rightExpression; 47 | } 48 | 49 | public boolean isPrimitiveComparison() { 50 | return isPrimitiveComparison; 51 | } 52 | 53 | @Override 54 | public void accept(ExpressionGenerator generator) { 55 | generator.generate(this); 56 | } 57 | 58 | @Override 59 | public Type getType() { 60 | return type; 61 | } 62 | 63 | @Override 64 | public void accept(StatementGenerator generator) { 65 | generator.generate(this); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /compiler/src/main/java/com/bendcap/enkel/compiler/domain/node/expression/ConstructorCall.java: -------------------------------------------------------------------------------- 1 | package com.bendcap.enkel.compiler.domain.node.expression; 2 | 3 | import com.bendcap.enkel.compiler.bytecodegenerator.expression.ExpressionGenerator; 4 | import com.bendcap.enkel.compiler.bytecodegenerator.statement.StatementGenerator; 5 | import com.bendcap.enkel.compiler.domain.type.ClassType; 6 | import com.bendcap.enkel.compiler.domain.type.Type; 7 | import lombok.ToString; 8 | 9 | import java.util.Collections; 10 | import java.util.List; 11 | 12 | /** 13 | * Created by KevinOfNeu on 2018/8/30 15:29. 14 | */ 15 | @ToString 16 | public class ConstructorCall implements Call { 17 | private List arguments; 18 | private Type type; 19 | private String identifier; 20 | 21 | public ConstructorCall(String identifier) { 22 | this(identifier, Collections.emptyList()); 23 | } 24 | 25 | public ConstructorCall(String className, List arguments) { 26 | this.type = new ClassType(className); 27 | this.arguments = arguments; 28 | this.identifier = type.getName(); 29 | } 30 | 31 | @Override 32 | public void accept(ExpressionGenerator genrator) { 33 | genrator.generate(this); 34 | } 35 | 36 | @Override 37 | public List getArguments() { 38 | return Collections.unmodifiableList(arguments); 39 | } 40 | 41 | @Override 42 | public String getIdentifier() { 43 | return identifier; 44 | } 45 | 46 | @Override 47 | public Type getType() { 48 | return type; 49 | } 50 | 51 | 52 | @Override 53 | public void accept(StatementGenerator generator) { 54 | generator.generate(this); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /compiler/src/main/java/com/bendcap/enkel/compiler/domain/node/expression/EmptyExpression.java: -------------------------------------------------------------------------------- 1 | package com.bendcap.enkel.compiler.domain.node.expression; 2 | 3 | import com.bendcap.enkel.compiler.bytecodegenerator.expression.ExpressionGenerator; 4 | import com.bendcap.enkel.compiler.bytecodegenerator.statement.StatementGenerator; 5 | import com.bendcap.enkel.compiler.domain.type.Type; 6 | 7 | /** 8 | * Created by KevinOfNeu on 2018/8/24 11:39. 9 | */ 10 | public class EmptyExpression implements Expression { 11 | private Type type; 12 | 13 | public EmptyExpression(Type type) { 14 | this.type = type; 15 | } 16 | 17 | @Override 18 | public void accept(ExpressionGenerator generator) { 19 | generator.generate(this); 20 | } 21 | 22 | @Override 23 | public Type getType() { 24 | return type; 25 | } 26 | 27 | @Override 28 | public void accept(StatementGenerator generator) { 29 | generator.generate(this); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /compiler/src/main/java/com/bendcap/enkel/compiler/domain/node/expression/Expression.java: -------------------------------------------------------------------------------- 1 | package com.bendcap.enkel.compiler.domain.node.expression; 2 | 3 | import com.bendcap.enkel.compiler.bytecodegenerator.expression.ExpressionGenerator; 4 | import com.bendcap.enkel.compiler.bytecodegenerator.statement.StatementGenerator; 5 | import com.bendcap.enkel.compiler.domain.node.statement.Statement; 6 | import com.bendcap.enkel.compiler.domain.type.Type; 7 | 8 | /** 9 | * Created by KevinOfNeu on 2018/8/31 11:56. 10 | */ 11 | public interface Expression extends Statement { 12 | Type getType(); 13 | void accept(ExpressionGenerator genrator); 14 | @Override 15 | void accept(StatementGenerator generator); 16 | } 17 | -------------------------------------------------------------------------------- /compiler/src/main/java/com/bendcap/enkel/compiler/domain/node/expression/FieldReference.java: -------------------------------------------------------------------------------- 1 | package com.bendcap.enkel.compiler.domain.node.expression; 2 | 3 | import com.bendcap.enkel.compiler.bytecodegenerator.expression.ExpressionGenerator; 4 | import com.bendcap.enkel.compiler.bytecodegenerator.statement.StatementGenerator; 5 | import com.bendcap.enkel.compiler.domain.scope.Field; 6 | import com.bendcap.enkel.compiler.domain.type.Type; 7 | 8 | /** 9 | * Created by KevinOfNeu on 2018/8/22 10:11. 10 | */ 11 | public class FieldReference implements Reference { 12 | private Field field; 13 | 14 | public FieldReference(Field field) { 15 | this.field = field; 16 | } 17 | 18 | public String geName() { 19 | return field.getName(); 20 | } 21 | 22 | @Override 23 | public void accept(ExpressionGenerator generator) { 24 | generator.generate(this); 25 | } 26 | 27 | 28 | @Override 29 | public void accept(StatementGenerator generator) { 30 | generator.generate(this); 31 | } 32 | 33 | @Override 34 | public Type getType() { 35 | return field.getType(); 36 | } 37 | 38 | public String getOwnerInternalName() { 39 | return field.getOwnerInternalName(); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /compiler/src/main/java/com/bendcap/enkel/compiler/domain/node/expression/FunctionCall.java: -------------------------------------------------------------------------------- 1 | package com.bendcap.enkel.compiler.domain.node.expression; 2 | 3 | import com.bendcap.enkel.compiler.bytecodegenerator.expression.ExpressionGenerator; 4 | import com.bendcap.enkel.compiler.bytecodegenerator.statement.StatementGenerator; 5 | import com.bendcap.enkel.compiler.domain.scope.FunctionSignature; 6 | import com.bendcap.enkel.compiler.domain.type.Type; 7 | 8 | import java.util.Collections; 9 | import java.util.List; 10 | 11 | /** 12 | * Created by KevinOfNeu on 2018/8/22 10:12. 13 | */ 14 | public class FunctionCall implements Call { 15 | private Expression owner; 16 | private FunctionSignature signature; 17 | private List arguments; 18 | private Type type; 19 | 20 | public FunctionCall(FunctionSignature signature, List arguments, Expression owner) { 21 | this.type = signature.getReturnType(); 22 | this.signature = signature; 23 | this.arguments = arguments; 24 | this.owner = owner; 25 | } 26 | 27 | public FunctionCall(FunctionSignature signature, List arguments, Type ownerType) { 28 | this(signature, arguments, new EmptyExpression(ownerType)); 29 | } 30 | 31 | 32 | public List getArguments() { 33 | return Collections.unmodifiableList(arguments); 34 | } 35 | 36 | @Override 37 | public String getIdentifier() { 38 | return signature.getName(); 39 | } 40 | 41 | public Type getOwnerType() { 42 | return owner.getType(); 43 | } 44 | 45 | public Expression getOwner() { 46 | return owner; 47 | } 48 | 49 | public FunctionSignature getSignature() { 50 | return signature; 51 | } 52 | 53 | @Override 54 | public void accept(ExpressionGenerator generator) { 55 | generator.generate(this); 56 | } 57 | 58 | @Override 59 | public void accept(StatementGenerator generator) { 60 | generator.generate(this); 61 | } 62 | 63 | @Override 64 | public Type getType() { 65 | return type; 66 | } 67 | } 68 | 69 | -------------------------------------------------------------------------------- /compiler/src/main/java/com/bendcap/enkel/compiler/domain/node/expression/LocalVariableReference.java: -------------------------------------------------------------------------------- 1 | package com.bendcap.enkel.compiler.domain.node.expression; 2 | 3 | import com.bendcap.enkel.compiler.bytecodegenerator.expression.ExpressionGenerator; 4 | import com.bendcap.enkel.compiler.bytecodegenerator.statement.StatementGenerator; 5 | import com.bendcap.enkel.compiler.domain.scope.LocalVariable; 6 | import com.bendcap.enkel.compiler.domain.type.Type; 7 | 8 | /** 9 | * Created by KevinOfNeu on 2018/8/31 23:09. 10 | */ 11 | public class LocalVariableReference implements Reference { 12 | private final LocalVariable variable; 13 | 14 | public LocalVariableReference(LocalVariable variable) { 15 | this.variable = variable; 16 | } 17 | 18 | @Override 19 | public String geName() { 20 | return variable.getName(); 21 | } 22 | 23 | @Override 24 | public void accept(ExpressionGenerator generator) { 25 | generator.generate(this); 26 | } 27 | 28 | @Override 29 | public Type getType() { 30 | return variable.getType(); 31 | } 32 | 33 | @Override 34 | public void accept(StatementGenerator generator) { 35 | generator.generate(this); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /compiler/src/main/java/com/bendcap/enkel/compiler/domain/node/expression/Parameter.java: -------------------------------------------------------------------------------- 1 | package com.bendcap.enkel.compiler.domain.node.expression; 2 | 3 | import com.bendcap.enkel.compiler.bytecodegenerator.expression.ExpressionGenerator; 4 | import com.bendcap.enkel.compiler.bytecodegenerator.statement.StatementGenerator; 5 | import com.bendcap.enkel.compiler.domain.type.Type; 6 | 7 | import java.util.Optional; 8 | 9 | /** 10 | * Created by KevinOfNeu on 2018/8/22 09:33. 11 | */ 12 | public class Parameter implements Expression { 13 | private final String name; 14 | private Optional defaultValue; 15 | private Type type; 16 | 17 | public Parameter(String name, Type type, Optional defaultValue) { 18 | this.type = type; 19 | this.name = name; 20 | this.defaultValue = defaultValue; 21 | } 22 | 23 | public String getName() { 24 | return name; 25 | } 26 | 27 | public Optional getDefaultValue() { 28 | return defaultValue; 29 | } 30 | 31 | @Override 32 | public void accept(ExpressionGenerator generator) { 33 | generator.generate(this); 34 | } 35 | 36 | @Override 37 | public void accept(StatementGenerator generator) { 38 | generator.generate(this); 39 | } 40 | 41 | @Override 42 | public Type getType() { 43 | return type; 44 | } 45 | 46 | @Override 47 | public boolean equals(Object o) { 48 | if (this == o) return true; 49 | if (o == null || getClass() != o.getClass()) return false; 50 | Parameter parameter = (Parameter) o; 51 | if (defaultValue != null ? !defaultValue.equals(parameter.defaultValue) : parameter.defaultValue != null) 52 | return false; 53 | return !(type != null ? !type.equals(parameter.type) : parameter.type != null); 54 | } 55 | 56 | @Override 57 | public int hashCode() { 58 | int result = defaultValue != null ? defaultValue.hashCode() : 0; 59 | result = 31 * result + (type != null ? type.hashCode() : 0); 60 | return result; 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /compiler/src/main/java/com/bendcap/enkel/compiler/domain/node/expression/Reference.java: -------------------------------------------------------------------------------- 1 | package com.bendcap.enkel.compiler.domain.node.expression; 2 | 3 | import com.bendcap.enkel.compiler.bytecodegenerator.expression.ExpressionGenerator; 4 | import com.bendcap.enkel.compiler.bytecodegenerator.statement.StatementGenerator; 5 | 6 | /** 7 | * Created by KevinOfNeu on 2018/8/31 23:07. 8 | */ 9 | public interface Reference extends Expression { 10 | String geName(); 11 | 12 | @Override 13 | void accept(ExpressionGenerator genrator); 14 | 15 | @Override 16 | void accept(StatementGenerator generator); 17 | } 18 | -------------------------------------------------------------------------------- /compiler/src/main/java/com/bendcap/enkel/compiler/domain/node/expression/SuperCall.java: -------------------------------------------------------------------------------- 1 | package com.bendcap.enkel.compiler.domain.node.expression; 2 | 3 | import com.bendcap.enkel.compiler.bytecodegenerator.expression.ExpressionGenerator; 4 | import com.bendcap.enkel.compiler.bytecodegenerator.statement.StatementGenerator; 5 | import com.bendcap.enkel.compiler.domain.type.BultInType; 6 | import com.bendcap.enkel.compiler.domain.type.Type; 7 | 8 | import java.util.Collections; 9 | import java.util.List; 10 | 11 | /** 12 | * Created by KevinOfNeu on 2018/8/30 15:59. 13 | */ 14 | public class SuperCall implements Call { 15 | public static final String SUPER_IDENTIFIER = "super"; 16 | private List arguments; 17 | 18 | public SuperCall() { 19 | this(Collections.emptyList()); 20 | } 21 | 22 | public SuperCall(List arguments) { 23 | this.arguments = arguments; 24 | } 25 | 26 | @Override 27 | public List getArguments() { 28 | return arguments; 29 | } 30 | 31 | @Override 32 | public String getIdentifier() { 33 | return SUPER_IDENTIFIER; 34 | } 35 | 36 | @Override 37 | public Type getType() { 38 | return BultInType.VOID; 39 | } 40 | 41 | @Override 42 | public void accept(ExpressionGenerator genrator) { 43 | genrator.generate(this); 44 | } 45 | 46 | @Override 47 | public void accept(StatementGenerator generator) { 48 | generator.generate(this); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /compiler/src/main/java/com/bendcap/enkel/compiler/domain/node/expression/Value.java: -------------------------------------------------------------------------------- 1 | package com.bendcap.enkel.compiler.domain.node.expression; 2 | 3 | import com.bendcap.enkel.compiler.bytecodegenerator.expression.ExpressionGenerator; 4 | import com.bendcap.enkel.compiler.bytecodegenerator.statement.StatementGenerator; 5 | import com.bendcap.enkel.compiler.domain.type.Type; 6 | 7 | /** 8 | * Created by KevinOfNeu on 2018/8/22 10:10. 9 | */ 10 | public class Value implements Expression { 11 | private String value; 12 | private Type type; 13 | 14 | public Value(Type type, String value) { 15 | this.type = type; 16 | this.value = value; 17 | } 18 | 19 | public String getValue() { 20 | return value; 21 | } 22 | 23 | 24 | @Override 25 | public void accept(ExpressionGenerator generator) { 26 | generator.generate(this); 27 | } 28 | 29 | @Override 30 | public void accept(StatementGenerator generator) { 31 | generator.generate(this); 32 | } 33 | 34 | @Override 35 | public Type getType() { 36 | return type; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /compiler/src/main/java/com/bendcap/enkel/compiler/domain/node/expression/arthimetic/Addition.java: -------------------------------------------------------------------------------- 1 | package com.bendcap.enkel.compiler.domain.node.expression.arthimetic; 2 | 3 | 4 | import com.bendcap.enkel.compiler.bytecodegenerator.expression.ExpressionGenerator; 5 | import com.bendcap.enkel.compiler.bytecodegenerator.statement.StatementGenerator; 6 | import com.bendcap.enkel.compiler.domain.node.expression.Expression; 7 | 8 | /** 9 | * Created by KevinOfNeu on 2018/8/23 16:46. 10 | */ 11 | public class Addition extends ArthimeticExpression { 12 | public Addition(Expression leftExpression, Expression rightExpression) { 13 | super(leftExpression, rightExpression); 14 | } 15 | 16 | @Override 17 | public void accept(ExpressionGenerator generator) { 18 | generator.generate(this); 19 | } 20 | 21 | @Override 22 | public void accept(StatementGenerator generator) { 23 | generator.generate(this); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /compiler/src/main/java/com/bendcap/enkel/compiler/domain/node/expression/arthimetic/ArthimeticExpression.java: -------------------------------------------------------------------------------- 1 | package com.bendcap.enkel.compiler.domain.node.expression.arthimetic; 2 | 3 | import com.bendcap.enkel.compiler.domain.node.expression.Expression; 4 | import com.bendcap.enkel.compiler.domain.type.BultInType; 5 | import com.bendcap.enkel.compiler.domain.type.Type; 6 | 7 | /** 8 | * Created by KevinOfNeu on 2018/8/23 16:42. 9 | */ 10 | public abstract class ArthimeticExpression implements Expression { 11 | private Expression leftExpression; 12 | private Expression rightExpression; 13 | private Type type; 14 | 15 | public ArthimeticExpression(Expression leftExpression, Expression rightExpression) { 16 | this.type = getCommonType(leftExpression, rightExpression); 17 | this.leftExpression = leftExpression; 18 | this.rightExpression = rightExpression; 19 | } 20 | 21 | private static Type getCommonType(Expression leftExpression, Expression rightExpression) { 22 | if (rightExpression.getType() == BultInType.STRING) return BultInType.STRING; 23 | return leftExpression.getType(); 24 | } 25 | 26 | public Expression getLeftExpression() { 27 | return leftExpression; 28 | } 29 | 30 | public Expression getRightExpression() { 31 | return rightExpression; 32 | } 33 | 34 | @Override 35 | public Type getType() { 36 | return type; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /compiler/src/main/java/com/bendcap/enkel/compiler/domain/node/expression/arthimetic/Division.java: -------------------------------------------------------------------------------- 1 | package com.bendcap.enkel.compiler.domain.node.expression.arthimetic; 2 | 3 | 4 | import com.bendcap.enkel.compiler.bytecodegenerator.expression.ExpressionGenerator; 5 | import com.bendcap.enkel.compiler.bytecodegenerator.statement.StatementGenerator; 6 | import com.bendcap.enkel.compiler.domain.node.expression.Expression; 7 | 8 | /** 9 | * Created by KevinOfNeu on 2018/8/23 16:52. 10 | */ 11 | public class Division extends ArthimeticExpression { 12 | public Division(Expression leftExpression, Expression rightExpression) { 13 | super(leftExpression, rightExpression); 14 | } 15 | 16 | @Override 17 | public void accept(ExpressionGenerator generator) { 18 | generator.generate(this); 19 | } 20 | 21 | @Override 22 | public void accept(StatementGenerator generator) { 23 | generator.generate(this); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /compiler/src/main/java/com/bendcap/enkel/compiler/domain/node/expression/arthimetic/Multiplication.java: -------------------------------------------------------------------------------- 1 | package com.bendcap.enkel.compiler.domain.node.expression.arthimetic; 2 | 3 | 4 | import com.bendcap.enkel.compiler.bytecodegenerator.expression.ExpressionGenerator; 5 | import com.bendcap.enkel.compiler.bytecodegenerator.statement.StatementGenerator; 6 | import com.bendcap.enkel.compiler.domain.node.expression.Expression; 7 | 8 | /** 9 | * Created by KevinOfNeu on 2018/8/23 16:53. 10 | */ 11 | public class Multiplication extends ArthimeticExpression{ 12 | public Multiplication(Expression leftExpression, Expression rightExpression) { 13 | super(leftExpression, rightExpression); 14 | } 15 | 16 | @Override 17 | public void accept(ExpressionGenerator generator) { 18 | generator.generate(this); 19 | } 20 | 21 | @Override 22 | public void accept(StatementGenerator generator) { 23 | generator.generate(this); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /compiler/src/main/java/com/bendcap/enkel/compiler/domain/node/expression/arthimetic/Substraction.java: -------------------------------------------------------------------------------- 1 | package com.bendcap.enkel.compiler.domain.node.expression.arthimetic; 2 | 3 | 4 | import com.bendcap.enkel.compiler.bytecodegenerator.expression.ExpressionGenerator; 5 | import com.bendcap.enkel.compiler.bytecodegenerator.statement.StatementGenerator; 6 | import com.bendcap.enkel.compiler.domain.node.expression.Expression; 7 | 8 | /** 9 | * Created by KevinOfNeu on 2018/8/23 16:53. 10 | */ 11 | public class Substraction extends ArthimeticExpression { 12 | public Substraction(Expression leftExpress, Expression rightExpress) { 13 | super(leftExpress, rightExpress); 14 | } 15 | 16 | @Override 17 | public void accept(ExpressionGenerator genrator) { 18 | genrator.generate(this); 19 | } 20 | 21 | @Override 22 | public void accept(StatementGenerator generator) { 23 | generator.generate(this); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /compiler/src/main/java/com/bendcap/enkel/compiler/domain/node/statement/Assignment.java: -------------------------------------------------------------------------------- 1 | package com.bendcap.enkel.compiler.domain.node.statement; 2 | 3 | 4 | import com.bendcap.enkel.compiler.bytecodegenerator.statement.StatementGenerator; 5 | import com.bendcap.enkel.compiler.domain.node.expression.Expression; 6 | 7 | /** 8 | * Created by KevinOfNeu on 2018/8/29 17:39. 9 | */ 10 | public class Assignment implements Statement { 11 | private String varName; 12 | private Expression expression; 13 | 14 | public Assignment(String varName, Expression expression) { 15 | this.varName = varName; 16 | this.expression = expression; 17 | } 18 | 19 | public Assignment(VariableDeclaration declarationStatement) { 20 | this.varName = declarationStatement.getName(); 21 | this.expression = declarationStatement.getExpression(); 22 | } 23 | 24 | 25 | public String getVarName() { 26 | return varName; 27 | } 28 | 29 | public Expression getExpression() { 30 | return expression; 31 | } 32 | 33 | @Override 34 | public void accept(StatementGenerator generator) { 35 | generator.generate(this); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /compiler/src/main/java/com/bendcap/enkel/compiler/domain/node/statement/Block.java: -------------------------------------------------------------------------------- 1 | package com.bendcap.enkel.compiler.domain.node.statement; 2 | 3 | import com.bendcap.enkel.compiler.bytecodegenerator.statement.StatementGenerator; 4 | import com.bendcap.enkel.compiler.domain.scope.Scope; 5 | 6 | import java.util.Collections; 7 | import java.util.List; 8 | 9 | /** 10 | * Created by KevinOfNeu on 2018/8/24 13:16. 11 | */ 12 | public class Block implements Statement { 13 | private List statements; 14 | private Scope scope; 15 | 16 | public Block( Scope scope, List statements) { 17 | this.statements = statements; 18 | this.scope = scope; 19 | } 20 | 21 | public static Block empty(Scope scope) { 22 | return new Block(scope, Collections.emptyList()); 23 | } 24 | 25 | @Override 26 | public void accept(StatementGenerator generator) { 27 | generator.generate(this); 28 | } 29 | 30 | public Scope getScope() { 31 | return scope; 32 | } 33 | 34 | public List getStatements() { 35 | return statements; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /compiler/src/main/java/com/bendcap/enkel/compiler/domain/node/statement/IfStatement.java: -------------------------------------------------------------------------------- 1 | package com.bendcap.enkel.compiler.domain.node.statement; 2 | 3 | 4 | import com.bendcap.enkel.compiler.bytecodegenerator.statement.StatementGenerator; 5 | import com.bendcap.enkel.compiler.domain.node.expression.Expression; 6 | 7 | import java.util.Optional; 8 | 9 | /** 10 | * Created by KevinOfNeu on 2018/8/24 22:42. 11 | */ 12 | public class IfStatement implements Statement { 13 | private Expression condition; 14 | private Statement trueStatement; 15 | private Optional falseStatement; 16 | 17 | public IfStatement(Expression condition, Statement trueStatement, Statement falseStatement) { 18 | this.condition = condition; 19 | this.trueStatement = trueStatement; 20 | this.falseStatement = Optional.ofNullable(falseStatement); 21 | } 22 | 23 | public IfStatement(Expression condition, Statement trueStatement) { 24 | this.condition = condition; 25 | this.trueStatement = trueStatement; 26 | this.falseStatement = Optional.empty(); 27 | } 28 | 29 | public Expression getCondition() { 30 | return condition; 31 | } 32 | 33 | public Statement getTrueStatement() { 34 | return trueStatement; 35 | } 36 | 37 | public Optional getFalseStatement() { 38 | return falseStatement; 39 | } 40 | 41 | @Override 42 | public void accept(StatementGenerator generator) { 43 | generator.generate(this); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /compiler/src/main/java/com/bendcap/enkel/compiler/domain/node/statement/PrintStatement.java: -------------------------------------------------------------------------------- 1 | package com.bendcap.enkel.compiler.domain.node.statement; 2 | 3 | 4 | import com.bendcap.enkel.compiler.bytecodegenerator.statement.StatementGenerator; 5 | import com.bendcap.enkel.compiler.domain.node.expression.Expression; 6 | 7 | /** 8 | * Created by KevinOfNeu on 2018/8/22 10:05. 9 | */ 10 | public class PrintStatement implements Statement { 11 | private Expression expression; 12 | 13 | public PrintStatement(Expression expression) { 14 | this.expression = expression; 15 | } 16 | 17 | public Expression getExpression() { 18 | return expression; 19 | } 20 | 21 | @Override 22 | public void accept(StatementGenerator generator) { 23 | generator.generate(this); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /compiler/src/main/java/com/bendcap/enkel/compiler/domain/node/statement/RangedForStatement.java: -------------------------------------------------------------------------------- 1 | package com.bendcap.enkel.compiler.domain.node.statement; 2 | 3 | import com.bendcap.enkel.compiler.bytecodegenerator.statement.StatementGenerator; 4 | import com.bendcap.enkel.compiler.domain.node.expression.Expression; 5 | import com.bendcap.enkel.compiler.domain.scope.Scope; 6 | import com.bendcap.enkel.compiler.domain.type.Type; 7 | import com.bendcap.enkel.compiler.utils.TypeChecker; 8 | import com.bendcap.enkel.compiler.exception.UnsupportedRangedLoopTypes; 9 | 10 | /** 11 | * Created by KevinOfNeu on 2018/8/29 17:44. 12 | */ 13 | public class RangedForStatement implements Statement { 14 | private Statement iteratorVariable; 15 | private Expression startExpression; 16 | private Expression endExpression; 17 | private Statement statement; 18 | private String iteratorVarName; 19 | private Scope scope; 20 | 21 | public RangedForStatement(Statement iteratorVariable, Expression startExpression, Expression endExpression, Statement statement, String iteratorVarName, Scope scope) { 22 | this.scope = scope; 23 | Type startExpressionType = startExpression.getType(); 24 | Type endExpressionType = endExpression.getType(); 25 | boolean typesAreIntegers = TypeChecker.isInt(startExpressionType) || TypeChecker.isInt(endExpressionType); 26 | if(!typesAreIntegers) { 27 | throw new UnsupportedRangedLoopTypes(startExpression, endExpression); 28 | } 29 | this.iteratorVariable = iteratorVariable; 30 | this.startExpression = startExpression; 31 | this.endExpression = endExpression; 32 | this.statement = statement; 33 | this.iteratorVarName = iteratorVarName; 34 | } 35 | 36 | public Statement getIteratorVariableStatement() { 37 | return iteratorVariable; 38 | } 39 | 40 | public Expression getStartExpression() { 41 | return startExpression; 42 | } 43 | 44 | public Expression getEndExpression() { 45 | return endExpression; 46 | } 47 | 48 | public Statement getStatement() { 49 | return statement; 50 | } 51 | 52 | public String getIteratorVarName() { 53 | return iteratorVarName; 54 | } 55 | 56 | public Scope getScope() { 57 | return scope; 58 | } 59 | 60 | @Override 61 | public void accept(StatementGenerator generator) { 62 | generator.generate(this); 63 | } 64 | 65 | public Type getType() { 66 | return startExpression.getType(); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /compiler/src/main/java/com/bendcap/enkel/compiler/domain/node/statement/ReturnStatement.java: -------------------------------------------------------------------------------- 1 | package com.bendcap.enkel.compiler.domain.node.statement; 2 | 3 | 4 | import com.bendcap.enkel.compiler.bytecodegenerator.statement.StatementGenerator; 5 | import com.bendcap.enkel.compiler.domain.node.expression.Expression; 6 | 7 | /** 8 | * Created by KevinOfNeu on 2018/8/24 11:41. 9 | */ 10 | public class ReturnStatement implements Statement { 11 | private Expression expression; 12 | 13 | public ReturnStatement(Expression expression) { 14 | this.expression = expression; 15 | } 16 | 17 | @Override 18 | public void accept(StatementGenerator generator) { 19 | generator.generate(this); 20 | } 21 | 22 | public Expression getExpression() { 23 | return expression; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /compiler/src/main/java/com/bendcap/enkel/compiler/domain/node/statement/Statement.java: -------------------------------------------------------------------------------- 1 | package com.bendcap.enkel.compiler.domain.node.statement; 2 | 3 | import com.bendcap.enkel.compiler.bytecodegenerator.statement.StatementGenerator; 4 | import com.bendcap.enkel.compiler.domain.node.Node; 5 | 6 | /** 7 | * Created by KevinOfNeu on 2018/8/22 09:25. 8 | */ 9 | @FunctionalInterface 10 | public interface Statement extends Node { 11 | void accept(StatementGenerator generator); 12 | } 13 | -------------------------------------------------------------------------------- /compiler/src/main/java/com/bendcap/enkel/compiler/domain/node/statement/VariableDeclaration.java: -------------------------------------------------------------------------------- 1 | package com.bendcap.enkel.compiler.domain.node.statement; 2 | 3 | 4 | import com.bendcap.enkel.compiler.bytecodegenerator.statement.StatementGenerator; 5 | import com.bendcap.enkel.compiler.domain.node.expression.Expression; 6 | 7 | /** 8 | * Created by KevinOfNeu on 2018/8/22 10:06. 9 | */ 10 | public class VariableDeclaration implements Statement { 11 | private String name; 12 | private Expression expression; 13 | 14 | public VariableDeclaration(String name, Expression expression) { 15 | this.name = name; 16 | this.expression = expression; 17 | } 18 | 19 | public String getName() { 20 | return name; 21 | } 22 | 23 | public Expression getExpression() { 24 | return expression; 25 | } 26 | 27 | @Override 28 | public void accept(StatementGenerator generator) { 29 | generator.generate(this); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /compiler/src/main/java/com/bendcap/enkel/compiler/domain/scope/ClassPathScope.java: -------------------------------------------------------------------------------- 1 | package com.bendcap.enkel.compiler.domain.scope; 2 | 3 | import com.bendcap.enkel.compiler.domain.type.Type; 4 | import com.bendcap.enkel.compiler.utils.ReflectionObjectToSignatureMapper; 5 | import org.apache.commons.lang3.reflect.ConstructorUtils; 6 | import org.apache.commons.lang3.reflect.MethodUtils; 7 | 8 | import java.lang.reflect.Constructor; 9 | import java.lang.reflect.Method; 10 | import java.util.List; 11 | import java.util.Optional; 12 | 13 | /** 14 | * Created by KevinOfNeu on 2018/8/31 17:00. 15 | */ 16 | public class ClassPathScope { 17 | public Optional getMethodSignature(Type owner, String methodName, List arguments) { 18 | try { 19 | Class methodOwnerClass = owner.getTypeClass(); 20 | Class[] params = arguments.stream() 21 | .map(Type::getTypeClass).toArray(Class[]::new); 22 | Method method = MethodUtils.getMatchingAccessibleMethod(methodOwnerClass, methodName, params); 23 | return Optional.of(ReflectionObjectToSignatureMapper.fromMethod(method)); 24 | } catch (Exception e) { 25 | return Optional.empty(); 26 | } 27 | } 28 | 29 | public Optional getConstructorSignature(String className, List arguments) { 30 | try { 31 | Class methodOwnerClass = Class.forName(className); 32 | Class[] params = arguments.stream() 33 | .map(Type::getTypeClass).toArray(Class[]::new); 34 | Constructor constructor = ConstructorUtils.getMatchingAccessibleConstructor(methodOwnerClass,params); 35 | return Optional.of(ReflectionObjectToSignatureMapper.fromConstructor(constructor)); 36 | } catch (Exception e) { 37 | return Optional.empty(); 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /compiler/src/main/java/com/bendcap/enkel/compiler/domain/scope/Field.java: -------------------------------------------------------------------------------- 1 | package com.bendcap.enkel.compiler.domain.scope; 2 | 3 | import com.bendcap.enkel.compiler.bytecodegenerator.FieldGenerator; 4 | import com.bendcap.enkel.compiler.domain.type.Type; 5 | 6 | /** 7 | * Created by KevinOfNeu on 2018/8/31 23:04. 8 | */ 9 | public class Field implements Variable { 10 | private final String name; 11 | private final Type owner; 12 | private final Type type; 13 | 14 | 15 | public Field(String name, Type owner, Type type) { 16 | this.name = name; 17 | this.type = type; 18 | this.owner = owner; 19 | } 20 | 21 | @Override 22 | public Type getType() { 23 | return type; 24 | } 25 | 26 | @Override 27 | public String getName() { 28 | return name; 29 | } 30 | 31 | public String getOwnerInternalName() { 32 | return owner.getInternalName(); 33 | } 34 | 35 | public void accept(FieldGenerator generator) { 36 | generator.generate(this); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /compiler/src/main/java/com/bendcap/enkel/compiler/domain/scope/FunctionSignature.java: -------------------------------------------------------------------------------- 1 | package com.bendcap.enkel.compiler.domain.scope; 2 | 3 | import com.bendcap.enkel.compiler.domain.node.expression.Argument; 4 | import com.bendcap.enkel.compiler.domain.node.expression.Parameter; 5 | import com.bendcap.enkel.compiler.domain.type.Type; 6 | import com.bendcap.enkel.compiler.exception.ParameterForNameNotFoundException; 7 | 8 | import java.util.List; 9 | import java.util.stream.IntStream; 10 | 11 | import static java.util.stream.Collectors.toList; 12 | 13 | /** 14 | * Created by KevinOfNeu on 2018/8/22 09:39. 15 | */ 16 | public class FunctionSignature { 17 | private String name; 18 | private List parameters; 19 | private Type returnType; 20 | 21 | public FunctionSignature(String name, List parameters, Type returnType) { 22 | this.name = name; 23 | this.parameters = parameters; 24 | this.returnType = returnType; 25 | } 26 | 27 | public String getName() { 28 | return name; 29 | } 30 | 31 | public List getParameters() { 32 | return parameters; 33 | } 34 | 35 | public Parameter getParameterForName(String name) { 36 | return parameters.stream() 37 | .filter(param -> param.getName().equals(name)) 38 | .findFirst() 39 | .orElseThrow(() -> new ParameterForNameNotFoundException(name, parameters)); 40 | } 41 | 42 | public int getIndexOfParameters(String parameterName) { 43 | Parameter parameter = getParameterForName(parameterName); 44 | return parameters.indexOf(parameter); 45 | } 46 | 47 | public boolean matches(String otherSignatureName, List arguments) { 48 | boolean namesAreEqual = this.name.equals(otherSignatureName); 49 | if (!namesAreEqual) return false; 50 | long nonDefaultParametersCount = parameters.stream() 51 | .filter(p -> !p.getDefaultValue().isPresent()) 52 | .count(); 53 | if (nonDefaultParametersCount > arguments.size()) return false; 54 | boolean isNamedArgList = arguments.stream().anyMatch(a -> a.getParameterName().isPresent()); 55 | if (isNamedArgList) { 56 | return areArgumentsAndParamsMatchedByName(arguments); 57 | } 58 | return areArgumentsAndParamsMatchedByIndex(arguments); 59 | } 60 | 61 | private boolean areArgumentsAndParamsMatchedByIndex(List arguments) { 62 | return IntStream.range(0, arguments.size()) 63 | .allMatch(i -> { 64 | Type argumentType = arguments.get(i).getType(); 65 | Type parameterType = parameters.get(i).getType(); 66 | return argumentType.equals(parameterType); 67 | }); 68 | 69 | } 70 | 71 | private boolean areArgumentsAndParamsMatchedByName(List arguments) { 72 | return arguments.stream().allMatch(a -> { 73 | String paramName = a.getParameterName().get(); 74 | return parameters.stream() 75 | .map(Parameter::getName) 76 | .anyMatch(paramName::equals); 77 | }); 78 | } 79 | 80 | public Type getReturnType() { 81 | return returnType; 82 | } 83 | 84 | @Override 85 | public boolean equals(Object o) { 86 | if (this == o) return true; 87 | if (o == null || getClass() != o.getClass()) return false; 88 | FunctionSignature that = (FunctionSignature) o; 89 | if (name != null ? !name.equals(that.name) : that.name != null) return false; 90 | if (parameters != null ? !parameters.equals(that.parameters) : that.parameters != null) return false; 91 | return !(returnType != null ? !returnType.equals(that.returnType) : that.returnType != null); 92 | } 93 | @Override 94 | public int hashCode() { 95 | int result = name != null ? name.hashCode() : 0; 96 | result = 31 * result + (parameters != null ? parameters.hashCode() : 0); 97 | result = 31 * result + (returnType != null ? returnType.hashCode() : 0); 98 | return result; 99 | } 100 | @Override 101 | public String toString() { 102 | return "FunctionSignature{" + 103 | "name='" + name + '\'' + 104 | ", parameters=" + parameters + 105 | ", returnType=" + returnType + 106 | '}'; 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /compiler/src/main/java/com/bendcap/enkel/compiler/domain/scope/LocalVariable.java: -------------------------------------------------------------------------------- 1 | package com.bendcap.enkel.compiler.domain.scope; 2 | 3 | import com.bendcap.enkel.compiler.domain.type.Type; 4 | 5 | /** 6 | * Created by KevinOfNeu on 2018/8/22 09:38. 7 | */ 8 | public class LocalVariable implements Variable{ 9 | private String name; 10 | private Type type; 11 | 12 | public LocalVariable(String name, Type type) { 13 | this.name = name; 14 | this.type = type; 15 | } 16 | 17 | @Override 18 | public String getName() { 19 | return name; 20 | } 21 | 22 | @Override 23 | public Type getType() { 24 | return type; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /compiler/src/main/java/com/bendcap/enkel/compiler/domain/scope/Scope.java: -------------------------------------------------------------------------------- 1 | package com.bendcap.enkel.compiler.domain.scope; 2 | 3 | import com.bendcap.enkel.compiler.domain.MetaData; 4 | import com.bendcap.enkel.compiler.domain.node.expression.Argument; 5 | import com.bendcap.enkel.compiler.domain.type.BultInType; 6 | import com.bendcap.enkel.compiler.domain.type.ClassType; 7 | import com.bendcap.enkel.compiler.domain.type.Type; 8 | import com.bendcap.enkel.compiler.exception.FieldNotFoundException; 9 | import com.bendcap.enkel.compiler.exception.LocalVariableNotFoundException; 10 | import com.bendcap.enkel.compiler.exception.MethodSignatureNotFoundException; 11 | import com.bendcap.enkel.compiler.exception.MethodWithNameAlreadyDefinedException; 12 | import com.google.common.collect.Lists; 13 | import org.apache.commons.collections4.map.LinkedMap; 14 | 15 | import java.util.*; 16 | 17 | import static java.util.stream.Collectors.toList; 18 | 19 | 20 | /** 21 | * Created by KevinOfNeu on 2018/8/22 09:37. 22 | */ 23 | public class Scope { 24 | private final List functionSignatures; 25 | private final MetaData metaData; 26 | private final LinkedMap localVariables; 27 | private final Map fields; 28 | 29 | public Scope(MetaData metaData) { 30 | this.metaData = metaData; 31 | functionSignatures = new ArrayList<>(); 32 | localVariables = new LinkedMap<>(); 33 | fields = new LinkedMap<>(); 34 | } 35 | 36 | public Scope(Scope scope) { 37 | metaData = scope.metaData; 38 | functionSignatures = Lists.newArrayList(scope.functionSignatures); 39 | fields = new LinkedMap<>(scope.fields); 40 | localVariables = new LinkedMap<>(scope.localVariables); 41 | } 42 | 43 | public void addSignature(FunctionSignature signature) { 44 | if(isParameterLessSignatureExists(signature.getName())) { 45 | throw new MethodWithNameAlreadyDefinedException(signature); 46 | } 47 | functionSignatures.add(signature); 48 | } 49 | 50 | public boolean isParameterLessSignatureExists(String identifier) { 51 | return isSignatureExists(identifier,Collections.emptyList()); 52 | } 53 | 54 | public boolean isSignatureExists(String identifier, List arguments) { 55 | if(identifier.equals("super")) return true; 56 | return functionSignatures.stream() 57 | .anyMatch(signature -> signature.matches(identifier,arguments)); 58 | } 59 | 60 | public FunctionSignature getMethodCallSignatureWithoutParameters(String identifier) { 61 | return getMethodCallSignature(identifier, Collections.emptyList()); 62 | } 63 | 64 | public FunctionSignature getConstructorCallSignature(String className,List arguments) { 65 | boolean isDifferentThanCurrentClass = !className.equals(getClassName()); 66 | if(isDifferentThanCurrentClass) { 67 | List argumentsTypes = arguments.stream().map(Argument::getType).collect(toList()); 68 | return new ClassPathScope().getConstructorSignature(className, argumentsTypes) 69 | .orElseThrow(() -> new MethodSignatureNotFoundException(this,className,arguments)); 70 | } 71 | return getConstructorCallSignatureForCurrentClass(arguments); 72 | } 73 | private FunctionSignature getConstructorCallSignatureForCurrentClass(List arguments) { 74 | return getMethodCallSignature(Optional.empty(), getClassName(), arguments); 75 | } 76 | public FunctionSignature getMethodCallSignature(Optional owner,String methodName,List arguments) { 77 | boolean isDifferentThanCurrentClass = owner.isPresent() && !owner.get().equals(getClassType()); 78 | if(isDifferentThanCurrentClass) { 79 | List argumentsTypes = arguments.stream().map(Argument::getType).collect(toList()); 80 | return new ClassPathScope().getMethodSignature(owner.get(), methodName, argumentsTypes) 81 | .orElseThrow(() -> new MethodSignatureNotFoundException(this,methodName,arguments)); 82 | } 83 | return getMethodCallSignature(methodName, arguments); 84 | } 85 | 86 | 87 | public FunctionSignature getMethodCallSignature(String identifier,List arguments) { 88 | if(identifier.equals("super")){ 89 | return new FunctionSignature("super", Collections.emptyList(), BultInType.VOID); 90 | } 91 | return functionSignatures.stream() 92 | .filter(signature -> signature.matches(identifier,arguments)) 93 | .findFirst() 94 | .orElseThrow(() -> new MethodSignatureNotFoundException(this, identifier,arguments)); 95 | } 96 | 97 | private String getSuperClassName() { 98 | return metaData.getSuperClassName(); 99 | } 100 | 101 | public void addLocalVariable(LocalVariable variable) { 102 | localVariables.put(variable.getName(),variable); 103 | } 104 | 105 | public LocalVariable getLocalVariable(String varName) { 106 | return Optional.ofNullable(localVariables.get(varName)) 107 | .orElseThrow(() -> new LocalVariableNotFoundException(this, varName)); 108 | } 109 | 110 | public int getLocalVariableIndex(String varName) { 111 | return localVariables.indexOf(varName); 112 | } 113 | 114 | public boolean isLocalVariableExists(String varName) { 115 | return localVariables.containsKey(varName); 116 | } 117 | 118 | public void addField(Field field) { 119 | fields.put(field.getName(),field); 120 | } 121 | public Field getField(String fieldName) { 122 | return Optional.ofNullable(fields.get(fieldName)) 123 | .orElseThrow(() -> new FieldNotFoundException(this, fieldName)); 124 | } 125 | public boolean isFieldExists(String varName) { 126 | return fields.containsKey(varName); 127 | } 128 | 129 | public String getClassName() { 130 | return metaData.getClassName(); 131 | } 132 | 133 | public String getSuperClassInternalName() { 134 | return new ClassType(getSuperClassName()).getInternalName(); 135 | } 136 | 137 | public Type getClassType() { 138 | String className = getClassName(); 139 | return new ClassType(className); 140 | } 141 | 142 | public String getClassInternalName() { 143 | return getClassType().getInternalName(); 144 | } 145 | 146 | } 147 | -------------------------------------------------------------------------------- /compiler/src/main/java/com/bendcap/enkel/compiler/domain/scope/Variable.java: -------------------------------------------------------------------------------- 1 | package com.bendcap.enkel.compiler.domain.scope; 2 | 3 | import com.bendcap.enkel.compiler.domain.type.Type; 4 | 5 | /** 6 | * Created by KevinOfNeu on 2018/8/31 22:17. 7 | */ 8 | public interface Variable { 9 | Type getType(); 10 | 11 | String getName(); 12 | } 13 | -------------------------------------------------------------------------------- /compiler/src/main/java/com/bendcap/enkel/compiler/domain/type/BultInType.java: -------------------------------------------------------------------------------- 1 | package com.bendcap.enkel.compiler.domain.type; 2 | 3 | /** 4 | * Created by KevinOfNeu on 2018/8/22 10:02. 5 | */ 6 | public enum BultInType implements Type { 7 | BOOLEAN("boolean",boolean.class,"Z", TypeSpecificOpcodes.INT), 8 | INT("int", int.class, "I", TypeSpecificOpcodes.INT), 9 | CHAR("char", char.class, "C", TypeSpecificOpcodes.INT), 10 | BYTE("byte", byte.class, "B", TypeSpecificOpcodes.INT), 11 | SHORT("short", short.class, "S", TypeSpecificOpcodes.INT), 12 | LONG("long", long.class, "J", TypeSpecificOpcodes.LONG), 13 | FLOAT("float", float.class, "F", TypeSpecificOpcodes.FLOAT), 14 | DOUBLE("double", double.class, "D", TypeSpecificOpcodes.DOUBLE), 15 | STRING("string", String.class, "Ljava/lang/String;", TypeSpecificOpcodes.OBJECT), 16 | BOOLEAN_ARR("bool[]", boolean[].class, "[B", TypeSpecificOpcodes.OBJECT), 17 | INT_ARR("int[]", int[].class, "[I", TypeSpecificOpcodes.OBJECT), 18 | CHAR_ARR("char[]", char[].class, "[C", TypeSpecificOpcodes.OBJECT), 19 | BYTE_ARR("byte[]", byte[].class, "[B", TypeSpecificOpcodes.OBJECT), 20 | SHORT_ARR("short[]", short[].class, "[S", TypeSpecificOpcodes.OBJECT), 21 | LONG_ARR("long[]", long[].class, "[J", TypeSpecificOpcodes.OBJECT), 22 | FLOAT_ARR("float[]", float[].class, "[F", TypeSpecificOpcodes.OBJECT), 23 | DOUBLE_ARR("double[]", double[].class, "[D", TypeSpecificOpcodes.OBJECT), 24 | STRING_ARR("string[]", String[].class, "[Ljava/lang/String;", TypeSpecificOpcodes.OBJECT), 25 | NONE("", null, "", TypeSpecificOpcodes.OBJECT), 26 | VOID("void", void.class, "V", TypeSpecificOpcodes.VOID); 27 | private final String name; 28 | private final Class typeClass; 29 | private final String descriptor; 30 | private final TypeSpecificOpcodes opcodes; 31 | 32 | BultInType(String name, Class typeClass, String descriptor, TypeSpecificOpcodes opcodes) { 33 | this.name = name; 34 | this.typeClass = typeClass; 35 | this.descriptor = descriptor; 36 | this.opcodes = opcodes; 37 | } 38 | 39 | @Override 40 | public String getName() { 41 | return name; 42 | } 43 | 44 | @Override 45 | public Class getTypeClass() { 46 | return typeClass; 47 | } 48 | 49 | @Override 50 | public String getDescriptor() { 51 | return descriptor; 52 | } 53 | 54 | @Override 55 | public String getInternalName() { 56 | return getDescriptor(); 57 | } 58 | 59 | @Override 60 | public int getLoadVariableOpcode() { 61 | return opcodes.getLoad(); 62 | } 63 | 64 | @Override 65 | public int getStoreVariableOpcode() { 66 | return opcodes.getStore(); 67 | } 68 | 69 | @Override 70 | public int getReturnOpcode() { 71 | return opcodes.getReturn(); 72 | } 73 | 74 | @Override 75 | public int getAddOpcode() { 76 | return opcodes.getAdd(); 77 | } 78 | 79 | @Override 80 | public int getSubstractOpcode() { 81 | return opcodes.getSubstract(); 82 | } 83 | 84 | @Override 85 | public int getMultiplyOpcode() { 86 | return opcodes.getMultiply(); 87 | } 88 | 89 | @Override 90 | public int getDividOpcode() { 91 | return opcodes.getDivide(); 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /compiler/src/main/java/com/bendcap/enkel/compiler/domain/type/ClassType.java: -------------------------------------------------------------------------------- 1 | package com.bendcap.enkel.compiler.domain.type; 2 | 3 | import com.google.common.collect.ImmutableMap; 4 | import lombok.ToString; 5 | import org.objectweb.asm.Opcodes; 6 | 7 | import java.util.Map; 8 | import java.util.Optional; 9 | 10 | /** 11 | * Created by KevinOfNeu on 2018/8/22 09:57. 12 | */ 13 | @ToString 14 | public class ClassType implements Type { 15 | private String name; 16 | 17 | private static final Map shortcuts = ImmutableMap.of( 18 | "List", "java.util.ArrayList" 19 | ); 20 | 21 | public ClassType(String name) { 22 | this.name = Optional.ofNullable(shortcuts.get(name)).orElse(name); 23 | } 24 | 25 | public static ClassType Integer() { 26 | return new ClassType("java.lang.Integer"); 27 | } 28 | 29 | public static ClassType Double() { 30 | return new ClassType("java.lang.Double"); 31 | } 32 | 33 | public static ClassType Boolean() { 34 | return new ClassType("java.lang.Boolean"); 35 | } 36 | 37 | public static ClassType Float() { 38 | return new ClassType("java.lang.Float"); 39 | } 40 | 41 | public static Type String() { 42 | return new ClassType("java.lang.String"); 43 | } 44 | 45 | @Override 46 | public String getName() { 47 | return name; 48 | } 49 | 50 | @Override 51 | public Class getTypeClass() { 52 | try { 53 | return Class.forName(name); 54 | } catch (ClassNotFoundException e) { 55 | throw new RuntimeException(); 56 | } 57 | } 58 | 59 | @Override 60 | public String getDescriptor() { 61 | return "L" + getInternalName() + ";"; 62 | } 63 | 64 | @Override 65 | public String getInternalName() { 66 | return name.replace(".", "/"); 67 | } 68 | 69 | @Override 70 | public int getLoadVariableOpcode() { 71 | return Opcodes.ALOAD; 72 | } 73 | 74 | @Override 75 | public int getStoreVariableOpcode() { 76 | return Opcodes.ASTORE; 77 | } 78 | 79 | @Override 80 | public int getReturnOpcode() { 81 | return Opcodes.ARETURN; 82 | } 83 | 84 | @Override 85 | public int getAddOpcode() { 86 | throw new RuntimeException("Addition operation not (yet ;) ) supported for custom objects"); 87 | } 88 | 89 | @Override 90 | public int getSubstractOpcode() { 91 | throw new RuntimeException("Substraction operation not (yet ;) ) supported for custom objects"); 92 | } 93 | 94 | @Override 95 | public int getMultiplyOpcode() { 96 | throw new RuntimeException("Multiplcation operation not (yet ;) ) supported for custom objects"); 97 | } 98 | 99 | @Override 100 | public int getDividOpcode() { 101 | throw new RuntimeException("Division operation not (yet ;) ) supported for custom objects"); 102 | } 103 | 104 | @Override 105 | public boolean equals(Object o) { 106 | if (this == o) return true; 107 | if (o == null || getClass() != o.getClass()) return false; 108 | ClassType classType = (ClassType) o; 109 | return !(name != null ? !name.equals(classType.name) : classType.name != null); 110 | } 111 | @Override 112 | public int hashCode() { 113 | return name != null ? name.hashCode() : 0; 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /compiler/src/main/java/com/bendcap/enkel/compiler/domain/type/Type.java: -------------------------------------------------------------------------------- 1 | package com.bendcap.enkel.compiler.domain.type; 2 | 3 | /** 4 | * Created by KevinOfNeu on 2018/8/22 09:31. 5 | */ 6 | public interface Type { 7 | String getName(); 8 | 9 | Class getTypeClass(); 10 | 11 | String getDescriptor(); 12 | 13 | String getInternalName(); 14 | 15 | int getLoadVariableOpcode(); 16 | 17 | int getStoreVariableOpcode(); 18 | 19 | int getReturnOpcode(); 20 | 21 | int getAddOpcode(); 22 | 23 | int getSubstractOpcode(); 24 | 25 | int getMultiplyOpcode(); 26 | 27 | int getDividOpcode(); 28 | } 29 | -------------------------------------------------------------------------------- /compiler/src/main/java/com/bendcap/enkel/compiler/domain/type/TypeSpecificOpcodes.java: -------------------------------------------------------------------------------- 1 | package com.bendcap.enkel.compiler.domain.type; 2 | 3 | import static org.objectweb.asm.Opcodes.*; 4 | 5 | /** 6 | * Created by KevinOfNeu on 2018/8/29 23:42. 7 | */ 8 | public enum TypeSpecificOpcodes { 9 | INT(ILOAD, ISTORE, IRETURN, IADD, ISUB, IMUL, IDIV), //values (-127,127) - one byte. 10 | LONG(LLOAD, LSTORE, LRETURN, LADD, LSUB, LMUL, LDIV), 11 | FLOAT(FLOAD, FSTORE, FRETURN, FADD, FSUB, FMUL, FDIV), 12 | DOUBLE(DLOAD, DSTORE, DRETURN, DADD, DSUB, DMUL, DDIV), 13 | VOID(ALOAD, ASTORE, RETURN, 0, 0, 0, 0), 14 | OBJECT(ALOAD, ASTORE, ARETURN, 0, 0, 0, 0); 15 | private final int load; 16 | private final int store; 17 | private final int ret; 18 | private final int add; 19 | private final int sub; 20 | private final int mul; 21 | private final int div; 22 | 23 | TypeSpecificOpcodes(int load, int store, int ret, int add, int sub, int mul, int div) { 24 | this.load = load; 25 | this.store = store; 26 | this.ret = ret; 27 | this.add = add; 28 | this.sub = sub; 29 | this.mul = mul; 30 | this.div = div; 31 | } 32 | 33 | public int getLoad() { 34 | return load; 35 | } 36 | 37 | public int getStore() { 38 | return store; 39 | } 40 | 41 | public int getReturn() { 42 | return ret; 43 | } 44 | 45 | public int getAdd() { 46 | return add; 47 | } 48 | 49 | public int getSubstract() { 50 | return sub; 51 | } 52 | 53 | public int getMultiply() { 54 | return mul; 55 | } 56 | 57 | public int getDivide() { 58 | return div; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /compiler/src/main/java/com/bendcap/enkel/compiler/exception/BadArgumentsToFunctionCallException.java: -------------------------------------------------------------------------------- 1 | package com.bendcap.enkel.compiler.exception; 2 | 3 | import com.bendcap.enkel.compiler.domain.node.expression.Call; 4 | 5 | /** 6 | * Created by KevinOfNeu on 2018/8/25 19:38. 7 | */ 8 | public class BadArgumentsToFunctionCallException extends RuntimeException { 9 | public BadArgumentsToFunctionCallException(Call functionCall) { 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /compiler/src/main/java/com/bendcap/enkel/compiler/exception/CalledFunctionDoesNotExistException.java: -------------------------------------------------------------------------------- 1 | package com.bendcap.enkel.compiler.exception; 2 | 3 | import com.bendcap.enkel.compiler.domain.node.expression.FunctionCall; 4 | import com.bendcap.enkel.compiler.domain.scope.Scope; 5 | 6 | /** 7 | * Created by KevinOfNeu on 2018/8/22 15:23. 8 | */ 9 | public class CalledFunctionDoesNotExistException extends CompilationException { 10 | FunctionCall functionCall; 11 | 12 | public CalledFunctionDoesNotExistException(FunctionCall functionCall) { 13 | this.functionCall = functionCall; 14 | } 15 | 16 | public CalledFunctionDoesNotExistException(FunctionCall functionCall, ReflectiveOperationException e) { 17 | this(functionCall); 18 | } 19 | 20 | public CalledFunctionDoesNotExistException(FunctionCall functionCall, Scope scope) { 21 | this(functionCall); 22 | } 23 | 24 | @Override 25 | public String getMessage() { 26 | return "Function call" + functionCall.toString() + "does not exists"; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /compiler/src/main/java/com/bendcap/enkel/compiler/exception/ClassNotFoundForNameException.java: -------------------------------------------------------------------------------- 1 | package com.bendcap.enkel.compiler.exception; 2 | 3 | /** 4 | * Created by KevinOfNeu on 2018/8/30 15:30. 5 | */ 6 | public class ClassNotFoundForNameException extends RuntimeException { 7 | public ClassNotFoundForNameException(String className) { 8 | super("class not found " + className); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /compiler/src/main/java/com/bendcap/enkel/compiler/exception/ComparisonBetweenDiferentTypesException.java: -------------------------------------------------------------------------------- 1 | package com.bendcap.enkel.compiler.exception; 2 | 3 | 4 | import com.bendcap.enkel.compiler.domain.node.expression.Expression; 5 | 6 | /** 7 | * Created by KevinOfNeu on 2018/8/24 23:00. 8 | */ 9 | public class ComparisonBetweenDiferentTypesException extends RuntimeException { 10 | public ComparisonBetweenDiferentTypesException(Expression leftExpression, Expression rightExpression) { 11 | super("Comparison between types " + leftExpression.getType() + " and " + rightExpression.getType() + " not yet supported"); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /compiler/src/main/java/com/bendcap/enkel/compiler/exception/CompilationException.java: -------------------------------------------------------------------------------- 1 | package com.bendcap.enkel.compiler.exception; 2 | 3 | /** 4 | * Created by KevinOfNeu on 2018/8/22 15:25. 5 | */ 6 | public class CompilationException extends RuntimeException { 7 | } 8 | -------------------------------------------------------------------------------- /compiler/src/main/java/com/bendcap/enkel/compiler/exception/FieldNotFoundException.java: -------------------------------------------------------------------------------- 1 | package com.bendcap.enkel.compiler.exception; 2 | 3 | import com.bendcap.enkel.compiler.domain.scope.Scope; 4 | 5 | /** 6 | * Created by KevinOfNeu on 2018/8/31 22:18. 7 | */ 8 | public class FieldNotFoundException extends RuntimeException { 9 | public FieldNotFoundException(Scope scope, String fieldName) { 10 | super("No field found for name " + fieldName + " found in scope" + scope); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /compiler/src/main/java/com/bendcap/enkel/compiler/exception/FunctionNameEqualClassException.java: -------------------------------------------------------------------------------- 1 | package com.bendcap.enkel.compiler.exception; 2 | 3 | /** 4 | * Created by KevinOfNeu on 2018/8/30 15:30. 5 | */ 6 | public class FunctionNameEqualClassException extends RuntimeException { 7 | public FunctionNameEqualClassException(String functionName) { 8 | super("Function name cannot be same as the class : " + functionName); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /compiler/src/main/java/com/bendcap/enkel/compiler/exception/LastStatementNotReturnableException.java: -------------------------------------------------------------------------------- 1 | package com.bendcap.enkel.compiler.exception; 2 | 3 | import com.bendcap.enkel.compiler.domain.node.statement.Statement; 4 | 5 | /** 6 | * Created by KevinOfNeu on 2018/8/24 13:14. 7 | */ 8 | public class LastStatementNotReturnableException extends RuntimeException { 9 | public LastStatementNotReturnableException(Statement lastStatement) { 10 | super("The statement " + lastStatement + " is a last statement in a functon, but it is not an expression!"); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /compiler/src/main/java/com/bendcap/enkel/compiler/exception/LocalVariableNotFoundException.java: -------------------------------------------------------------------------------- 1 | package com.bendcap.enkel.compiler.exception; 2 | 3 | import com.bendcap.enkel.compiler.domain.scope.Scope; 4 | 5 | /** 6 | * Created by KevinOfNeu on 2018/8/22 09:51. 7 | */ 8 | public class LocalVariableNotFoundException extends RuntimeException { 9 | public LocalVariableNotFoundException(Scope scope, String variableName) { 10 | super("No local varaible found for name " + variableName + "found in scope" + scope); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /compiler/src/main/java/com/bendcap/enkel/compiler/exception/MethodSignatureNotFoundException.java: -------------------------------------------------------------------------------- 1 | package com.bendcap.enkel.compiler.exception; 2 | 3 | import com.bendcap.enkel.compiler.domain.node.expression.Argument; 4 | import com.bendcap.enkel.compiler.domain.scope.Scope; 5 | import com.bendcap.enkel.compiler.domain.type.Type; 6 | 7 | import java.util.List; 8 | 9 | /** 10 | * Created by KevinOfNeu on 2018/8/22 09:46. 11 | */ 12 | public class MethodSignatureNotFoundException extends RuntimeException { 13 | public MethodSignatureNotFoundException(Scope scope, String methodName, List parameterTypes) { 14 | super("There is no method '" + methodName + "' with parameters " + parameterTypes); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /compiler/src/main/java/com/bendcap/enkel/compiler/exception/MethodWithNameAlreadyDefinedException.java: -------------------------------------------------------------------------------- 1 | package com.bendcap.enkel.compiler.exception; 2 | 3 | import com.bendcap.enkel.compiler.domain.scope.FunctionSignature; 4 | 5 | /** 6 | * Created by KevinOfNeu on 2018/8/31 12:12. 7 | */ 8 | public class MethodWithNameAlreadyDefinedException extends RuntimeException{ 9 | public MethodWithNameAlreadyDefinedException(FunctionSignature signature) { 10 | super("Method already defined in scope :" + signature); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /compiler/src/main/java/com/bendcap/enkel/compiler/exception/MixedComparisonNotAllowedException.java: -------------------------------------------------------------------------------- 1 | package com.bendcap.enkel.compiler.exception; 2 | 3 | import com.bendcap.enkel.compiler.domain.type.Type; 4 | 5 | /** 6 | * Created by KevinOfNeu on 2018/9/2 14:54. 7 | */ 8 | public class MixedComparisonNotAllowedException extends RuntimeException { 9 | public MixedComparisonNotAllowedException(Type leftType, Type rightType) { 10 | super("Comparison between object and primitive is not supported :" + leftType + " | " + rightType); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /compiler/src/main/java/com/bendcap/enkel/compiler/exception/NoVisitorReturnedValueException.java: -------------------------------------------------------------------------------- 1 | package com.bendcap.enkel.compiler.exception; 2 | 3 | /** 4 | * Created by KevinOfNeu on 2018/8/22 16:07. 5 | */ 6 | public class NoVisitorReturnedValueException extends CompilationException { 7 | public NoVisitorReturnedValueException() { 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /compiler/src/main/java/com/bendcap/enkel/compiler/exception/ParameterForNameNotFoundException.java: -------------------------------------------------------------------------------- 1 | package com.bendcap.enkel.compiler.exception; 2 | 3 | import com.bendcap.enkel.compiler.domain.node.expression.Parameter; 4 | 5 | import java.util.List; 6 | 7 | /** 8 | * Created by KevinOfNeu on 2018/8/26 21:58. 9 | */ 10 | public class ParameterForNameNotFoundException extends RuntimeException{ 11 | public ParameterForNameNotFoundException(String name, List parameters) { 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /compiler/src/main/java/com/bendcap/enkel/compiler/exception/UnsupportedArthimeticOperationException.java: -------------------------------------------------------------------------------- 1 | package com.bendcap.enkel.compiler.exception; 2 | 3 | import com.bendcap.enkel.compiler.domain.node.expression.arthimetic.ArthimeticExpression; 4 | import com.bendcap.enkel.compiler.domain.node.expression.Expression; 5 | 6 | /** 7 | * Created by KevinOfNeu on 2018/8/23 16:17. 8 | */ 9 | public class UnsupportedArthimeticOperationException extends RuntimeException{ 10 | public UnsupportedArthimeticOperationException(ArthimeticExpression expression) { 11 | super(prepareMesage(expression)); 12 | } 13 | private static String prepareMesage(ArthimeticExpression expression) { 14 | Expression leftExpression = expression.getLeftExpression(); 15 | Expression rightExpression = expression.getRightExpression(); 16 | return "Unsupported arthimetic operation between " + leftExpression +" and "+rightExpression; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /compiler/src/main/java/com/bendcap/enkel/compiler/exception/UnsupportedRangedLoopTypes.java: -------------------------------------------------------------------------------- 1 | package com.bendcap.enkel.compiler.exception; 2 | 3 | 4 | import com.bendcap.enkel.compiler.domain.node.expression.Expression; 5 | 6 | /** 7 | * Created by KevinOfNeu on 2018/8/29 17:42. 8 | */ 9 | public class UnsupportedRangedLoopTypes extends RuntimeException { 10 | public UnsupportedRangedLoopTypes(Expression startExpression, Expression endExpression) { 11 | super("Only integer types are supported so far"); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /compiler/src/main/java/com/bendcap/enkel/compiler/exception/WrongArgumentNameException.java: -------------------------------------------------------------------------------- 1 | package com.bendcap.enkel.compiler.exception; 2 | 3 | import com.bendcap.enkel.compiler.domain.node.expression.Argument; 4 | import com.bendcap.enkel.compiler.domain.node.expression.Parameter; 5 | 6 | import java.util.List; 7 | 8 | /** 9 | * Created by KevinOfNeu on 2018/8/31 12:14. 10 | */ 11 | public class WrongArgumentNameException extends RuntimeException{ 12 | public WrongArgumentNameException(Argument argument, List parameters) { 13 | super("You are trying to call method with argument name" + argument.getParameterName().get() + " where parameters = " + parameters); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /compiler/src/main/java/com/bendcap/enkel/compiler/parsing/EnkelTreeWalkErrorListener.java: -------------------------------------------------------------------------------- 1 | package com.bendcap.enkel.compiler.parsing; 2 | 3 | import org.antlr.v4.runtime.BaseErrorListener; 4 | import org.antlr.v4.runtime.RecognitionException; 5 | import org.antlr.v4.runtime.Recognizer; 6 | 7 | /** 8 | * Created by KevinOfNeu on 2018/7/18 21:14. 9 | */ 10 | public class EnkelTreeWalkErrorListener extends BaseErrorListener { 11 | @Override 12 | public void syntaxError(Recognizer recognizer, Object offendingSymbol, int line, int charPositionInLine, String msg, RecognitionException e) { 13 | String errorFormat = "You fucked up at line %d,char %d :(. Details:%n%s"; 14 | String errorMsg = String.format(errorFormat, line, charPositionInLine, msg); 15 | System.err.println(errorMsg); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /compiler/src/main/java/com/bendcap/enkel/compiler/parsing/Parser.java: -------------------------------------------------------------------------------- 1 | package com.bendcap.enkel.compiler.parsing; 2 | 3 | import com.bendcap.enkel.antlr.EnkelLexer; 4 | import com.bendcap.enkel.antlr.EnkelParser; 5 | import com.bendcap.enkel.compiler.domain.CompilationUnit; 6 | import com.bendcap.enkel.compiler.parsing.EnkelTreeWalkErrorListener; 7 | import com.bendcap.enkel.compiler.parsing.visitor.CompilationUnitVisitor; 8 | import org.antlr.v4.runtime.ANTLRErrorListener; 9 | import org.antlr.v4.runtime.ANTLRFileStream; 10 | import org.antlr.v4.runtime.CharStream; 11 | import org.antlr.v4.runtime.CommonTokenStream; 12 | 13 | import java.io.IOException; 14 | 15 | /** 16 | * Created by KevinOfNeu on 2018/8/21 09:15. 17 | */ 18 | public class Parser { 19 | public CompilationUnit getCompilationUnit(String fileAbsolutePath) throws IOException { 20 | CharStream charStream = new ANTLRFileStream(fileAbsolutePath); 21 | EnkelLexer lexer = new EnkelLexer(charStream); 22 | CommonTokenStream tokenStream = new CommonTokenStream(lexer); 23 | EnkelParser parser = new EnkelParser(tokenStream); 24 | 25 | ANTLRErrorListener errorListener = new EnkelTreeWalkErrorListener(); 26 | parser.addErrorListener(errorListener); 27 | 28 | CompilationUnitVisitor compilationUnitVisitor = new CompilationUnitVisitor(); 29 | return parser.compilationUnit().accept(compilationUnitVisitor); 30 | } 31 | } -------------------------------------------------------------------------------- /compiler/src/main/java/com/bendcap/enkel/compiler/parsing/visitor/ClassVisitor.java: -------------------------------------------------------------------------------- 1 | package com.bendcap.enkel.compiler.parsing.visitor; 2 | 3 | import com.bendcap.enkel.antlr.EnkelBaseVisitor; 4 | import com.bendcap.enkel.antlr.EnkelParser; 5 | import com.bendcap.enkel.compiler.domain.ClassDeclaration; 6 | import com.bendcap.enkel.compiler.domain.Constructor; 7 | import com.bendcap.enkel.compiler.domain.Function; 8 | import com.bendcap.enkel.compiler.domain.MetaData; 9 | import com.bendcap.enkel.compiler.domain.node.expression.ConstructorCall; 10 | import com.bendcap.enkel.compiler.domain.node.expression.FunctionCall; 11 | import com.bendcap.enkel.compiler.domain.node.expression.Parameter; 12 | import com.bendcap.enkel.compiler.domain.node.statement.Block; 13 | import com.bendcap.enkel.compiler.domain.scope.Field; 14 | import com.bendcap.enkel.compiler.domain.scope.FunctionSignature; 15 | import com.bendcap.enkel.compiler.domain.scope.Scope; 16 | import com.bendcap.enkel.compiler.domain.type.BultInType; 17 | 18 | import java.util.Arrays; 19 | import java.util.Collections; 20 | import java.util.List; 21 | import java.util.Optional; 22 | 23 | import static java.util.stream.Collectors.toList; 24 | 25 | /** 26 | * Created by KevinOfNeu on 2018/8/21 09:24. 27 | */ 28 | public class ClassVisitor extends EnkelBaseVisitor { 29 | private Scope scope; 30 | 31 | @Override 32 | public ClassDeclaration visitClassDeclaration(EnkelParser.ClassDeclarationContext ctx) { 33 | MetaData metaData = new MetaData(ctx.className().getText(),"java.lang.Object"); 34 | scope = new Scope(metaData); 35 | String name = ctx.className().getText(); 36 | FieldVisitor fieldVisitor = new FieldVisitor(scope); 37 | FunctionSignatureVisitor functionSignatureVisitor = new FunctionSignatureVisitor(scope); 38 | List methodsCtx = ctx.classBody().function(); 39 | List fields = ctx.classBody().field().stream() 40 | .map(field -> field.accept(fieldVisitor)) 41 | .peek(scope::addField) 42 | .collect(toList()); 43 | methodsCtx.stream() 44 | .map(method -> method.functionDeclaration().accept(functionSignatureVisitor)) 45 | .forEach(scope::addSignature); 46 | boolean defaultConstructorExists = scope.isParameterLessSignatureExists(name); 47 | addDefaultConstructorSignatureToScope(name, defaultConstructorExists); 48 | List methods = methodsCtx.stream() 49 | .map(method -> method.accept(new FunctionVisitor(scope))) 50 | .collect(toList()); 51 | if(!defaultConstructorExists) { 52 | methods.add(getDefaultConstructor()); 53 | } 54 | boolean startMethodDefined = scope.isParameterLessSignatureExists("start"); 55 | if(startMethodDefined) { 56 | methods.add(getGeneratedMainMethod()); 57 | } 58 | 59 | return new ClassDeclaration(name, fields, methods); 60 | } 61 | 62 | private void addDefaultConstructorSignatureToScope(String name, boolean defaultConstructorExists) { 63 | if(!defaultConstructorExists) { 64 | FunctionSignature constructorSignature = new FunctionSignature(name, Collections.emptyList(), BultInType.VOID); 65 | scope.addSignature(constructorSignature); 66 | } 67 | } 68 | 69 | private Constructor getDefaultConstructor() { 70 | FunctionSignature signature = scope.getMethodCallSignatureWithoutParameters(scope.getClassName()); 71 | Constructor constructor = new Constructor(signature, Block.empty(scope)); 72 | return constructor; 73 | } 74 | private Function getGeneratedMainMethod() { 75 | Parameter args = new Parameter("args", BultInType.STRING_ARR, Optional.empty()); 76 | FunctionSignature functionSignature = new FunctionSignature("main", Collections.singletonList(args), BultInType.VOID); 77 | ConstructorCall constructorCall = new ConstructorCall(scope.getClassName()); 78 | FunctionSignature startFunSignature = new FunctionSignature("start", Collections.emptyList(), BultInType.VOID); 79 | FunctionCall startFunctionCall = new FunctionCall(startFunSignature, Collections.emptyList(), scope.getClassType()); 80 | Block block = new Block(new Scope(scope), Arrays.asList(constructorCall,startFunctionCall)); 81 | return new Function(functionSignature, block); 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /compiler/src/main/java/com/bendcap/enkel/compiler/parsing/visitor/CompilationUnitVisitor.java: -------------------------------------------------------------------------------- 1 | package com.bendcap.enkel.compiler.parsing.visitor; 2 | 3 | import com.bendcap.enkel.antlr.EnkelBaseVisitor; 4 | import com.bendcap.enkel.antlr.EnkelParser; 5 | import com.bendcap.enkel.compiler.domain.ClassDeclaration; 6 | import com.bendcap.enkel.compiler.domain.CompilationUnit; 7 | 8 | /** 9 | * Created by KevinOfNeu on 2018/8/21 09:20. 10 | */ 11 | public class CompilationUnitVisitor extends EnkelBaseVisitor { 12 | @Override 13 | public CompilationUnit visitCompilationUnit(EnkelParser.CompilationUnitContext ctx) { 14 | ClassVisitor classVisitor = new ClassVisitor(); 15 | EnkelParser.ClassDeclarationContext classDeclarationContext = ctx.classDeclaration(); 16 | ClassDeclaration classDeclaration = classDeclarationContext.accept(classVisitor); 17 | return new CompilationUnit(classDeclaration); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /compiler/src/main/java/com/bendcap/enkel/compiler/parsing/visitor/FieldVisitor.java: -------------------------------------------------------------------------------- 1 | package com.bendcap.enkel.compiler.parsing.visitor; 2 | 3 | import com.bendcap.enkel.antlr.EnkelBaseVisitor; 4 | import com.bendcap.enkel.antlr.EnkelParser; 5 | import com.bendcap.enkel.compiler.domain.scope.Field; 6 | import com.bendcap.enkel.compiler.domain.scope.Scope; 7 | import com.bendcap.enkel.compiler.domain.type.Type; 8 | import com.bendcap.enkel.compiler.utils.TypeResolver; 9 | import org.antlr.v4.runtime.misc.NotNull; 10 | 11 | /** 12 | * Created by KevinOfNeu on 2018/8/31 22:19. 13 | */ 14 | public class FieldVisitor extends EnkelBaseVisitor { 15 | private final Scope scope; 16 | 17 | public FieldVisitor(Scope scope) { 18 | this.scope = scope; 19 | } 20 | 21 | @Override 22 | public Field visitField(@NotNull EnkelParser.FieldContext ctx) { 23 | Type owner = scope.getClassType(); 24 | Type type = TypeResolver.getFromTypeContext(ctx.type()); 25 | String name = ctx.name().getText(); 26 | return new Field(name, owner, type); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /compiler/src/main/java/com/bendcap/enkel/compiler/parsing/visitor/FunctionSignatureVisitor.java: -------------------------------------------------------------------------------- 1 | package com.bendcap.enkel.compiler.parsing.visitor; 2 | 3 | import com.bendcap.enkel.antlr.EnkelBaseVisitor; 4 | import com.bendcap.enkel.antlr.EnkelParser; 5 | import com.bendcap.enkel.compiler.domain.node.expression.Parameter; 6 | import com.bendcap.enkel.compiler.domain.scope.FunctionSignature; 7 | import com.bendcap.enkel.compiler.domain.scope.Scope; 8 | import com.bendcap.enkel.compiler.domain.type.Type; 9 | import com.bendcap.enkel.compiler.parsing.visitor.expression.ExpressionVisitor; 10 | import com.bendcap.enkel.compiler.parsing.visitor.expression.function.ParameterExpressionListVisitor; 11 | import com.bendcap.enkel.compiler.utils.TypeResolver; 12 | import org.antlr.v4.runtime.misc.NotNull; 13 | 14 | import java.util.Collections; 15 | import java.util.List; 16 | 17 | /** 18 | * Created by KevinOfNeu on 2018/8/31 12:17. 19 | */ 20 | public class FunctionSignatureVisitor extends EnkelBaseVisitor { 21 | private final ExpressionVisitor expressionVisitor; 22 | public FunctionSignatureVisitor(Scope scope) { 23 | this.expressionVisitor = new ExpressionVisitor(scope); 24 | } 25 | @Override 26 | public FunctionSignature visitFunctionDeclaration(@NotNull EnkelParser.FunctionDeclarationContext ctx) { 27 | String functionName = ctx.functionName().getText(); 28 | Type returnType = TypeResolver.getFromTypeContext(ctx.type()); 29 | EnkelParser.ParametersListContext parametersCtx = ctx.parametersList(); 30 | if(parametersCtx != null) { 31 | List parameters = parametersCtx.accept(new ParameterExpressionListVisitor(expressionVisitor)); 32 | return new FunctionSignature(functionName, parameters, returnType); 33 | } 34 | return new FunctionSignature(functionName, Collections.emptyList(), returnType); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /compiler/src/main/java/com/bendcap/enkel/compiler/parsing/visitor/FunctionVisitor.java: -------------------------------------------------------------------------------- 1 | package com.bendcap.enkel.compiler.parsing.visitor; 2 | 3 | import com.bendcap.enkel.antlr.EnkelBaseVisitor; 4 | import com.bendcap.enkel.antlr.EnkelParser; 5 | import com.bendcap.enkel.compiler.domain.Constructor; 6 | import com.bendcap.enkel.compiler.domain.Function; 7 | import com.bendcap.enkel.compiler.domain.scope.FunctionSignature; 8 | import com.bendcap.enkel.compiler.domain.scope.LocalVariable; 9 | import com.bendcap.enkel.compiler.domain.scope.Scope; 10 | import com.bendcap.enkel.compiler.domain.node.statement.Statement; 11 | import com.bendcap.enkel.compiler.parsing.visitor.statement.StatementVisitor; 12 | import org.antlr.v4.runtime.misc.NotNull; 13 | 14 | /** 15 | * Created by KevinOfNeu on 2018/8/22 16:03. 16 | */ 17 | public class FunctionVisitor extends EnkelBaseVisitor { 18 | private Scope scope; 19 | 20 | public FunctionVisitor(Scope scope) { 21 | this.scope = new Scope(scope); 22 | } 23 | 24 | @Override 25 | public Function visitFunction(@NotNull EnkelParser.FunctionContext ctx) { 26 | FunctionSignature signature = ctx.functionDeclaration().accept(new FunctionSignatureVisitor(scope)); 27 | scope.addLocalVariable(new LocalVariable("this",scope.getClassType())); 28 | addParametersAsLocalVariables(signature); 29 | Statement block = getBlock(ctx); 30 | if(signature.getName().equals(scope.getClassName())) { 31 | return new Constructor(signature,block); 32 | } 33 | return new Function(signature, block); 34 | } 35 | 36 | 37 | private void addParametersAsLocalVariables(FunctionSignature signature) { 38 | signature.getParameters().stream() 39 | .forEach(param -> scope.addLocalVariable(new LocalVariable(param.getName(), param.getType()))); 40 | } 41 | 42 | private Statement getBlock(EnkelParser.FunctionContext functionContext) { 43 | StatementVisitor statementVisitor = new StatementVisitor(scope); 44 | EnkelParser.BlockContext blockContext = functionContext.block(); 45 | return blockContext.accept(statementVisitor); 46 | } 47 | 48 | 49 | } 50 | -------------------------------------------------------------------------------- /compiler/src/main/java/com/bendcap/enkel/compiler/parsing/visitor/expression/ArithmeticExpressionVisitor.java: -------------------------------------------------------------------------------- 1 | package com.bendcap.enkel.compiler.parsing.visitor.expression; 2 | 3 | import com.bendcap.enkel.antlr.EnkelBaseVisitor; 4 | import com.bendcap.enkel.antlr.EnkelParser; 5 | import com.bendcap.enkel.compiler.domain.node.expression.arthimetic.*; 6 | import com.bendcap.enkel.compiler.domain.node.expression.Expression; 7 | import org.antlr.v4.runtime.misc.NotNull; 8 | 9 | /** 10 | * Created by KevinOfNeu on 2018/8/31 12:19. 11 | */ 12 | public class ArithmeticExpressionVisitor extends EnkelBaseVisitor { 13 | private final ExpressionVisitor expressionVisitor; 14 | public ArithmeticExpressionVisitor(ExpressionVisitor expressionVisitor) { 15 | this.expressionVisitor = expressionVisitor; 16 | } 17 | @Override 18 | public ArthimeticExpression visitAdd(@NotNull EnkelParser.AddContext ctx) { 19 | EnkelParser.ExpressionContext leftExpression = ctx.expression(0); 20 | EnkelParser.ExpressionContext rightExpression = ctx.expression(1); 21 | Expression leftExpress = leftExpression.accept(expressionVisitor); 22 | Expression rightExpress = rightExpression.accept(expressionVisitor); 23 | return new Addition(leftExpress, rightExpress); 24 | } 25 | @Override 26 | public ArthimeticExpression visitMultiply(@NotNull EnkelParser.MultiplyContext ctx) { 27 | EnkelParser.ExpressionContext leftExpression = ctx.expression(0); 28 | EnkelParser.ExpressionContext rightExpression = ctx.expression(1); 29 | Expression leftExpress = leftExpression.accept(expressionVisitor); 30 | Expression rightExpress = rightExpression.accept(expressionVisitor); 31 | return new Multiplication(leftExpress, rightExpress); 32 | } 33 | @Override 34 | public ArthimeticExpression visitSubstract(@NotNull EnkelParser.SubstractContext ctx) { 35 | EnkelParser.ExpressionContext leftExpression = ctx.expression(0); 36 | EnkelParser.ExpressionContext rightExpression = ctx.expression(1); 37 | Expression leftExpress = leftExpression.accept(expressionVisitor); 38 | Expression rightExpress = rightExpression.accept(expressionVisitor); 39 | return new Substraction(leftExpress, rightExpress); 40 | } 41 | @Override 42 | public ArthimeticExpression visitDivide(@NotNull EnkelParser.DivideContext ctx) { 43 | EnkelParser.ExpressionContext leftExpression = ctx.expression(0); 44 | EnkelParser.ExpressionContext rightExpression = ctx.expression(1); 45 | Expression leftExpress = leftExpression.accept(expressionVisitor); 46 | Expression rightExpress = rightExpression.accept(expressionVisitor); 47 | return new Division(leftExpress, rightExpress); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /compiler/src/main/java/com/bendcap/enkel/compiler/parsing/visitor/expression/ConditionalExpressionVisitor.java: -------------------------------------------------------------------------------- 1 | package com.bendcap.enkel.compiler.parsing.visitor.expression; 2 | 3 | import com.bendcap.enkel.antlr.EnkelBaseVisitor; 4 | import com.bendcap.enkel.antlr.EnkelParser; 5 | import com.bendcap.enkel.compiler.domain.CompareSign; 6 | import com.bendcap.enkel.compiler.domain.node.expression.ConditionalExpression; 7 | import com.bendcap.enkel.compiler.domain.node.expression.Expression; 8 | import com.bendcap.enkel.compiler.domain.node.expression.Value; 9 | import com.bendcap.enkel.compiler.domain.type.BultInType; 10 | import org.antlr.v4.runtime.misc.NotNull; 11 | 12 | /** 13 | * Created by KevinOfNeu on 2018/8/31 12:19. 14 | */ 15 | public class ConditionalExpressionVisitor extends EnkelBaseVisitor { 16 | private final ExpressionVisitor expressionVisitor; 17 | public ConditionalExpressionVisitor(ExpressionVisitor expressionVisitor) { 18 | this.expressionVisitor = expressionVisitor; 19 | } 20 | @Override 21 | public ConditionalExpression visitConditionalExpression(@NotNull EnkelParser.ConditionalExpressionContext ctx) { 22 | EnkelParser.ExpressionContext leftExpressionCtx = ctx.expression(0); 23 | EnkelParser.ExpressionContext rightExpressionCtx = ctx.expression(1); 24 | Expression leftExpression = leftExpressionCtx.accept(expressionVisitor); 25 | Expression rightExpression = rightExpressionCtx != null ? rightExpressionCtx.accept(expressionVisitor) : new Value(BultInType.INT, "0"); 26 | CompareSign cmpSign = ctx.cmp != null ? CompareSign.fromString(ctx.cmp.getText()) : CompareSign.NOT_EQUAL; 27 | return new ConditionalExpression(leftExpression, rightExpression, cmpSign); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /compiler/src/main/java/com/bendcap/enkel/compiler/parsing/visitor/expression/ExpressionVisitor.java: -------------------------------------------------------------------------------- 1 | package com.bendcap.enkel.compiler.parsing.visitor.expression; 2 | 3 | import com.bendcap.enkel.antlr.EnkelBaseVisitor; 4 | import com.bendcap.enkel.antlr.EnkelParser; 5 | import com.bendcap.enkel.compiler.domain.node.expression.ConditionalExpression; 6 | import com.bendcap.enkel.compiler.domain.node.expression.Expression; 7 | import com.bendcap.enkel.compiler.domain.scope.Scope; 8 | import com.bendcap.enkel.compiler.parsing.visitor.expression.function.CallExpressionVisitor; 9 | import org.antlr.v4.runtime.misc.NotNull; 10 | 11 | /** 12 | * Created by KevinOfNeu on 2018/8/31 12:20. 13 | */ 14 | public class ExpressionVisitor extends EnkelBaseVisitor { 15 | private final ArithmeticExpressionVisitor arithmeticExpressionVisitor; 16 | private final VariableReferenceExpressionVisitor variableReferenceExpressionVisitor; 17 | private final ValueExpressionVisitor valueExpressionVisitor; 18 | private final CallExpressionVisitor callExpressionVisitor; 19 | private final ConditionalExpressionVisitor conditionalExpressionVisitor; 20 | public ExpressionVisitor(Scope scope) { 21 | arithmeticExpressionVisitor = new ArithmeticExpressionVisitor(this); 22 | variableReferenceExpressionVisitor = new VariableReferenceExpressionVisitor(scope); 23 | valueExpressionVisitor = new ValueExpressionVisitor(); 24 | callExpressionVisitor = new CallExpressionVisitor(this, scope); 25 | conditionalExpressionVisitor = new ConditionalExpressionVisitor(this); 26 | } 27 | @Override 28 | public Expression visitVarReference(@NotNull EnkelParser.VarReferenceContext ctx) { 29 | return variableReferenceExpressionVisitor.visitVarReference(ctx); 30 | } 31 | @Override 32 | public Expression visitValue(@NotNull EnkelParser.ValueContext ctx) { 33 | return valueExpressionVisitor.visitValue(ctx); 34 | } 35 | @Override 36 | public Expression visitFunctionCall(@NotNull EnkelParser.FunctionCallContext ctx) { 37 | return callExpressionVisitor.visitFunctionCall(ctx); 38 | } 39 | @Override 40 | public Expression visitConstructorCall(@NotNull EnkelParser.ConstructorCallContext ctx) { 41 | return callExpressionVisitor.visitConstructorCall(ctx); 42 | } 43 | @Override 44 | public Expression visitSupercall(@NotNull EnkelParser.SupercallContext ctx) { 45 | return callExpressionVisitor.visitSupercall(ctx); 46 | } 47 | @Override 48 | public Expression visitAdd(@NotNull EnkelParser.AddContext ctx) { 49 | return arithmeticExpressionVisitor.visitAdd(ctx); 50 | } 51 | @Override 52 | public Expression visitMultiply(@NotNull EnkelParser.MultiplyContext ctx) { 53 | return arithmeticExpressionVisitor.visitMultiply(ctx); 54 | } 55 | @Override 56 | public Expression visitSubstract(@NotNull EnkelParser.SubstractContext ctx) { 57 | return arithmeticExpressionVisitor.visitSubstract(ctx); 58 | } 59 | @Override 60 | public Expression visitDivide(@NotNull EnkelParser.DivideContext ctx) { 61 | return arithmeticExpressionVisitor.visitDivide(ctx); 62 | } 63 | @Override 64 | public ConditionalExpression visitConditionalExpression(@NotNull EnkelParser.ConditionalExpressionContext ctx) { 65 | return conditionalExpressionVisitor.visitConditionalExpression(ctx); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /compiler/src/main/java/com/bendcap/enkel/compiler/parsing/visitor/expression/ValueExpressionVisitor.java: -------------------------------------------------------------------------------- 1 | package com.bendcap.enkel.compiler.parsing.visitor.expression; 2 | 3 | import com.bendcap.enkel.antlr.EnkelBaseVisitor; 4 | import com.bendcap.enkel.antlr.EnkelParser; 5 | import com.bendcap.enkel.compiler.domain.node.expression.Value; 6 | import com.bendcap.enkel.compiler.domain.type.Type; 7 | import com.bendcap.enkel.compiler.utils.TypeResolver; 8 | import org.antlr.v4.runtime.misc.NotNull; 9 | 10 | /** 11 | * Created by KevinOfNeu on 2018/8/31 12:20. 12 | */ 13 | public class ValueExpressionVisitor extends EnkelBaseVisitor { 14 | @Override 15 | public Value visitValue(@NotNull EnkelParser.ValueContext ctx) { 16 | String value = ctx.getText(); 17 | Type type = TypeResolver.getFromValue(ctx); 18 | return new Value(type, value); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /compiler/src/main/java/com/bendcap/enkel/compiler/parsing/visitor/expression/VariableReferenceExpressionVisitor.java: -------------------------------------------------------------------------------- 1 | package com.bendcap.enkel.compiler.parsing.visitor.expression; 2 | 3 | import com.bendcap.enkel.antlr.EnkelBaseVisitor; 4 | import com.bendcap.enkel.antlr.EnkelParser; 5 | import com.bendcap.enkel.compiler.domain.node.expression.FieldReference; 6 | import com.bendcap.enkel.compiler.domain.node.expression.LocalVariableReference; 7 | import com.bendcap.enkel.compiler.domain.node.expression.Reference; 8 | import com.bendcap.enkel.compiler.domain.scope.Field; 9 | import com.bendcap.enkel.compiler.domain.scope.LocalVariable; 10 | import com.bendcap.enkel.compiler.domain.scope.Scope; 11 | import org.antlr.v4.runtime.misc.NotNull; 12 | 13 | /** 14 | * Created by KevinOfNeu on 2018/8/31 12:21. 15 | */ 16 | public class VariableReferenceExpressionVisitor extends EnkelBaseVisitor { 17 | private final Scope scope; 18 | public VariableReferenceExpressionVisitor(Scope scope) { 19 | this.scope = scope; 20 | } 21 | @Override 22 | public Reference visitVarReference(@NotNull EnkelParser.VarReferenceContext ctx) { 23 | String varName = ctx.getText(); 24 | if(scope.isFieldExists(varName)) { 25 | Field field = scope.getField(varName); 26 | return new FieldReference(field); 27 | } 28 | LocalVariable variable = scope.getLocalVariable(varName); 29 | return new LocalVariableReference(variable); 30 | } 31 | } 32 | 33 | -------------------------------------------------------------------------------- /compiler/src/main/java/com/bendcap/enkel/compiler/parsing/visitor/expression/function/ArgumentExpressionVisitor.java: -------------------------------------------------------------------------------- 1 | package com.bendcap.enkel.compiler.parsing.visitor.expression.function; 2 | 3 | import com.bendcap.enkel.antlr.EnkelBaseVisitor; 4 | import com.bendcap.enkel.antlr.EnkelParser; 5 | import com.bendcap.enkel.compiler.domain.node.expression.Argument; 6 | import com.bendcap.enkel.compiler.domain.node.expression.Expression; 7 | import com.bendcap.enkel.compiler.parsing.visitor.expression.ExpressionVisitor; 8 | import org.antlr.v4.runtime.misc.NotNull; 9 | 10 | import java.util.Optional; 11 | 12 | /** 13 | * Created by KevinOfNeu on 2018/8/31 12:21. 14 | */ 15 | public class ArgumentExpressionVisitor extends EnkelBaseVisitor { 16 | private final ExpressionVisitor expressionVisitor; 17 | public ArgumentExpressionVisitor(ExpressionVisitor expressionVisitor) { 18 | this.expressionVisitor = expressionVisitor; 19 | } 20 | @Override 21 | public Argument visitArgument(@NotNull EnkelParser.ArgumentContext ctx) { 22 | Expression value = ctx.expression().accept(expressionVisitor); 23 | return new Argument(value, Optional.empty()); 24 | } 25 | @Override 26 | public Argument visitNamedArgument(@NotNull EnkelParser.NamedArgumentContext ctx) { 27 | Expression value = ctx.expression().accept(expressionVisitor); 28 | String name = ctx.name().getText(); 29 | return new Argument(value, Optional.of(name)); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /compiler/src/main/java/com/bendcap/enkel/compiler/parsing/visitor/expression/function/ArgumentExpressionsListVisitor.java: -------------------------------------------------------------------------------- 1 | package com.bendcap.enkel.compiler.parsing.visitor.expression.function; 2 | 3 | import com.bendcap.enkel.antlr.EnkelBaseVisitor; 4 | import com.bendcap.enkel.antlr.EnkelParser; 5 | import com.bendcap.enkel.compiler.domain.node.expression.Argument; 6 | import com.bendcap.enkel.compiler.parsing.visitor.expression.ExpressionVisitor; 7 | import org.antlr.v4.runtime.misc.NotNull; 8 | 9 | import java.util.List; 10 | 11 | import static java.util.stream.Collectors.toList; 12 | 13 | /** 14 | * Created by KevinOfNeu on 2018/8/31 12:21. 15 | */ 16 | public class ArgumentExpressionsListVisitor extends EnkelBaseVisitor> { 17 | private final ExpressionVisitor expressionVisitor; 18 | public ArgumentExpressionsListVisitor(ExpressionVisitor expressionVisitor) { 19 | this.expressionVisitor = expressionVisitor; 20 | } 21 | @Override 22 | public List visitUnnamedArgumentsList(@NotNull EnkelParser.UnnamedArgumentsListContext ctx) { 23 | ArgumentExpressionVisitor argumentExpressionVisitor = new ArgumentExpressionVisitor(expressionVisitor); 24 | return ctx.argument().stream() 25 | .map(a -> a.accept(argumentExpressionVisitor)).collect(toList()); 26 | } 27 | @Override 28 | public List visitNamedArgumentsList(@NotNull EnkelParser.NamedArgumentsListContext ctx) { 29 | ArgumentExpressionVisitor argumentExpressionVisitor = new ArgumentExpressionVisitor(expressionVisitor); 30 | return ctx.namedArgument().stream() 31 | .map(a -> a.accept(argumentExpressionVisitor)).collect(toList()); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /compiler/src/main/java/com/bendcap/enkel/compiler/parsing/visitor/expression/function/CallExpressionVisitor.java: -------------------------------------------------------------------------------- 1 | package com.bendcap.enkel.compiler.parsing.visitor.expression.function; 2 | 3 | import com.bendcap.enkel.antlr.EnkelBaseVisitor; 4 | import com.bendcap.enkel.antlr.EnkelParser; 5 | import com.bendcap.enkel.compiler.domain.node.expression.*; 6 | import com.bendcap.enkel.compiler.domain.scope.FunctionSignature; 7 | import com.bendcap.enkel.compiler.domain.scope.LocalVariable; 8 | import com.bendcap.enkel.compiler.domain.scope.Scope; 9 | import com.bendcap.enkel.compiler.domain.type.ClassType; 10 | import com.bendcap.enkel.compiler.exception.FunctionNameEqualClassException; 11 | import com.bendcap.enkel.compiler.parsing.visitor.expression.ExpressionVisitor; 12 | import org.antlr.v4.runtime.misc.NotNull; 13 | 14 | import java.util.Collections; 15 | import java.util.List; 16 | import java.util.Optional; 17 | 18 | /** 19 | * Created by KevinOfNeu on 2018/8/31 12:22. 20 | */ 21 | public class CallExpressionVisitor extends EnkelBaseVisitor { 22 | private final ExpressionVisitor expressionVisitor; 23 | private final Scope scope; 24 | 25 | public CallExpressionVisitor(ExpressionVisitor expressionVisitor, Scope scope) { 26 | this.expressionVisitor = expressionVisitor; 27 | this.scope = scope; 28 | } 29 | 30 | @Override 31 | public Call visitFunctionCall(@NotNull EnkelParser.FunctionCallContext ctx) { 32 | String functionName = ctx.functionName().getText(); 33 | if (functionName.equals(scope.getClassName())) { 34 | throw new FunctionNameEqualClassException(functionName); 35 | } 36 | List arguments = getArgumentsForCall(ctx.argumentList()); 37 | boolean ownerIsExplicit = ctx.owner != null; 38 | if (ownerIsExplicit) { 39 | Expression owner = ctx.owner.accept(expressionVisitor); 40 | FunctionSignature signature = scope.getMethodCallSignature(Optional.of(owner.getType()),functionName, arguments); 41 | return new FunctionCall(signature, arguments, owner); 42 | } 43 | ClassType thisType = new ClassType(scope.getClassName()); 44 | FunctionSignature signature = scope.getMethodCallSignature(functionName, arguments); 45 | LocalVariable thisVariable = new LocalVariable("this",thisType); 46 | return new FunctionCall(signature, arguments, new LocalVariableReference(thisVariable)); 47 | } 48 | 49 | @Override 50 | public Call visitConstructorCall(@NotNull EnkelParser.ConstructorCallContext ctx) { 51 | String className = ctx.className().getText(); 52 | List arguments = getArgumentsForCall(ctx.argumentList()); 53 | return new ConstructorCall(className, arguments); 54 | } 55 | 56 | @Override 57 | public Call visitSupercall(@NotNull EnkelParser.SupercallContext ctx) { 58 | List arguments = getArgumentsForCall(ctx.argumentList()); 59 | return new SuperCall(arguments); 60 | } 61 | 62 | private List getArgumentsForCall(EnkelParser.ArgumentListContext argumentsListCtx) { 63 | if (argumentsListCtx != null) { 64 | ArgumentExpressionsListVisitor visitor = new ArgumentExpressionsListVisitor(expressionVisitor); 65 | return argumentsListCtx.accept(visitor); 66 | } 67 | return Collections.emptyList(); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /compiler/src/main/java/com/bendcap/enkel/compiler/parsing/visitor/expression/function/ParameterExpressionListVisitor.java: -------------------------------------------------------------------------------- 1 | package com.bendcap.enkel.compiler.parsing.visitor.expression.function; 2 | 3 | import com.bendcap.enkel.antlr.EnkelBaseVisitor; 4 | import com.bendcap.enkel.antlr.EnkelParser; 5 | import com.bendcap.enkel.compiler.domain.node.expression.Parameter; 6 | import com.bendcap.enkel.compiler.parsing.visitor.expression.ExpressionVisitor; 7 | import com.google.common.collect.Lists; 8 | import org.antlr.v4.runtime.misc.NotNull; 9 | 10 | import java.util.ArrayList; 11 | import java.util.List; 12 | 13 | /** 14 | * Created by KevinOfNeu on 2018/8/31 12:22. 15 | */ 16 | public class ParameterExpressionListVisitor extends EnkelBaseVisitor> { 17 | private final ExpressionVisitor expressionVisitor; 18 | public ParameterExpressionListVisitor(ExpressionVisitor expressionVisitor) { 19 | this.expressionVisitor = expressionVisitor; 20 | } 21 | @Override 22 | public List visitParametersList(@NotNull EnkelParser.ParametersListContext ctx) { 23 | List paramsCtx = ctx.parameter(); 24 | ParameterExpressionVisitor parameterExpressionVisitor = new ParameterExpressionVisitor(expressionVisitor); 25 | List parameters = new ArrayList<>(); 26 | if(paramsCtx != null) { 27 | List params = Lists.transform(paramsCtx, p -> p.accept(parameterExpressionVisitor)); 28 | parameters.addAll(params); 29 | } 30 | List paramsWithDefaultValueCtx = ctx.parameterWithDefaultValue(); 31 | if(paramsWithDefaultValueCtx != null) { 32 | List params = Lists.transform(paramsWithDefaultValueCtx, p -> p.accept(parameterExpressionVisitor)); 33 | parameters.addAll(params); 34 | } 35 | return parameters; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /compiler/src/main/java/com/bendcap/enkel/compiler/parsing/visitor/expression/function/ParameterExpressionVisitor.java: -------------------------------------------------------------------------------- 1 | package com.bendcap.enkel.compiler.parsing.visitor.expression.function; 2 | 3 | import com.bendcap.enkel.antlr.EnkelBaseVisitor; 4 | import com.bendcap.enkel.antlr.EnkelParser; 5 | import com.bendcap.enkel.compiler.domain.node.expression.Expression; 6 | import com.bendcap.enkel.compiler.domain.node.expression.Parameter; 7 | import com.bendcap.enkel.compiler.domain.type.Type; 8 | import com.bendcap.enkel.compiler.parsing.visitor.expression.ExpressionVisitor; 9 | import com.bendcap.enkel.compiler.utils.TypeResolver; 10 | import org.antlr.v4.runtime.misc.NotNull; 11 | 12 | import java.util.Optional; 13 | 14 | /** 15 | * Created by KevinOfNeu on 2018/8/31 12:22. 16 | */ 17 | public class ParameterExpressionVisitor extends EnkelBaseVisitor { 18 | private final ExpressionVisitor expressionVisitor; 19 | public ParameterExpressionVisitor(ExpressionVisitor expressionVisitor) { 20 | this.expressionVisitor = expressionVisitor; 21 | } 22 | @Override 23 | public Parameter visitParameter(@NotNull EnkelParser.ParameterContext ctx) { 24 | String name = ctx.ID().getText(); 25 | Type type = TypeResolver.getFromTypeContext(ctx.type()); 26 | return new Parameter(name, type, Optional.empty()); 27 | } 28 | @Override 29 | public Parameter visitParameterWithDefaultValue(@NotNull EnkelParser.ParameterWithDefaultValueContext ctx) { 30 | String name = ctx.ID().getText(); 31 | Type type = TypeResolver.getFromTypeContext(ctx.type()); 32 | Expression defaultValue = ctx.defaultValue.accept(expressionVisitor); 33 | return new Parameter(name, type, Optional.of(defaultValue)); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /compiler/src/main/java/com/bendcap/enkel/compiler/parsing/visitor/statement/AssignmentStatementVisitor.java: -------------------------------------------------------------------------------- 1 | package com.bendcap.enkel.compiler.parsing.visitor.statement; 2 | 3 | import com.bendcap.enkel.antlr.EnkelBaseVisitor; 4 | import com.bendcap.enkel.antlr.EnkelParser; 5 | import com.bendcap.enkel.compiler.domain.node.expression.Expression; 6 | import com.bendcap.enkel.compiler.domain.node.statement.Assignment; 7 | import com.bendcap.enkel.compiler.parsing.visitor.expression.ExpressionVisitor; 8 | import org.antlr.v4.runtime.misc.NotNull; 9 | 10 | /** 11 | * Created by KevinOfNeu on 2018/8/31 23:11. 12 | */ 13 | public class AssignmentStatementVisitor extends EnkelBaseVisitor { 14 | private final ExpressionVisitor expressionVisitor; 15 | 16 | public AssignmentStatementVisitor(ExpressionVisitor expressionVisitor) { 17 | this.expressionVisitor = expressionVisitor; 18 | } 19 | 20 | @Override 21 | public Assignment visitAssignment(@NotNull EnkelParser.AssignmentContext ctx) { 22 | EnkelParser.ExpressionContext expressionCtx = ctx.expression(); 23 | Expression expression = expressionCtx.accept(expressionVisitor); 24 | String varName = ctx.name().getText(); 25 | return new Assignment(varName, expression); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /compiler/src/main/java/com/bendcap/enkel/compiler/parsing/visitor/statement/BlockStatementVisitor.java: -------------------------------------------------------------------------------- 1 | package com.bendcap.enkel.compiler.parsing.visitor.statement; 2 | 3 | import com.bendcap.enkel.antlr.EnkelBaseVisitor; 4 | import com.bendcap.enkel.antlr.EnkelParser; 5 | import com.bendcap.enkel.compiler.domain.node.statement.Block; 6 | import com.bendcap.enkel.compiler.domain.node.statement.Statement; 7 | import com.bendcap.enkel.compiler.domain.scope.Scope; 8 | import org.antlr.v4.runtime.misc.NotNull; 9 | 10 | import java.util.List; 11 | import java.util.stream.Collectors; 12 | 13 | /** 14 | * Created by KevinOfNeu on 2018/8/31 12:23. 15 | */ 16 | public class BlockStatementVisitor extends EnkelBaseVisitor { 17 | private final Scope scope; 18 | public BlockStatementVisitor(Scope scope) { 19 | this.scope = scope; 20 | } 21 | @Override 22 | public Block visitBlock(@NotNull EnkelParser.BlockContext ctx) { 23 | List blockstatementsCtx = ctx.statement(); 24 | Scope newScope = new Scope(scope); 25 | StatementVisitor statementVisitor = new StatementVisitor(newScope); 26 | List statements = blockstatementsCtx.stream().map(smtt -> smtt.accept(statementVisitor)).collect(Collectors.toList()); 27 | return new Block(newScope, statements); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /compiler/src/main/java/com/bendcap/enkel/compiler/parsing/visitor/statement/ForStatementVisitor.java: -------------------------------------------------------------------------------- 1 | package com.bendcap.enkel.compiler.parsing.visitor.statement; 2 | 3 | import com.bendcap.enkel.antlr.EnkelBaseVisitor; 4 | import com.bendcap.enkel.antlr.EnkelParser; 5 | import com.bendcap.enkel.compiler.domain.node.expression.Expression; 6 | import com.bendcap.enkel.compiler.domain.scope.LocalVariable; 7 | import com.bendcap.enkel.compiler.domain.scope.Scope; 8 | import com.bendcap.enkel.compiler.domain.node.statement.Assignment; 9 | import com.bendcap.enkel.compiler.domain.node.statement.RangedForStatement; 10 | import com.bendcap.enkel.compiler.domain.node.statement.Statement; 11 | import com.bendcap.enkel.compiler.domain.node.statement.VariableDeclaration; 12 | import com.bendcap.enkel.compiler.parsing.visitor.expression.ExpressionVisitor; 13 | 14 | /** 15 | * Created by KevinOfNeu on 2018/8/29 17:44. 16 | */ 17 | public class ForStatementVisitor extends EnkelBaseVisitor { 18 | private Scope scope; 19 | private ExpressionVisitor expressionVisitor; 20 | 21 | public ForStatementVisitor(Scope scope) { 22 | this.scope = scope; 23 | expressionVisitor = new ExpressionVisitor(this.scope); 24 | } 25 | 26 | @Override 27 | public RangedForStatement visitForStatement(EnkelParser.ForStatementContext ctx) { 28 | Scope newScope = new Scope(scope); 29 | EnkelParser.ForConditionsContext forConditionsContext = ctx.forConditions(); 30 | Expression startExpression = forConditionsContext.startExpr.accept(expressionVisitor); 31 | Expression endExpression = forConditionsContext.endExpr.accept(expressionVisitor); 32 | EnkelParser.VariableReferenceContext iterator = forConditionsContext.iterator; 33 | StatementVisitor statementVisitor = new StatementVisitor(newScope); 34 | String varName = iterator.getText(); 35 | if(newScope.isLocalVariableExists(varName)) { 36 | Statement iteratorVariable = new Assignment(varName, startExpression); 37 | Statement statement = ctx.statement().accept(statementVisitor); 38 | return new RangedForStatement(iteratorVariable, startExpression, endExpression,statement, varName, newScope); 39 | } else { 40 | newScope.addLocalVariable(new LocalVariable(varName, startExpression.getType())); 41 | Statement iteratorVariable = new VariableDeclaration(varName, startExpression); 42 | Statement statement = ctx.statement().accept(statementVisitor); 43 | return new RangedForStatement(iteratorVariable, startExpression, endExpression,statement, varName,newScope); 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /compiler/src/main/java/com/bendcap/enkel/compiler/parsing/visitor/statement/IfStatementVisitor.java: -------------------------------------------------------------------------------- 1 | package com.bendcap.enkel.compiler.parsing.visitor.statement; 2 | 3 | import com.bendcap.enkel.antlr.EnkelBaseVisitor; 4 | import com.bendcap.enkel.antlr.EnkelParser; 5 | import com.bendcap.enkel.compiler.domain.node.expression.Expression; 6 | import com.bendcap.enkel.compiler.domain.node.statement.IfStatement; 7 | import com.bendcap.enkel.compiler.domain.node.statement.Statement; 8 | import com.bendcap.enkel.compiler.parsing.visitor.expression.ExpressionVisitor; 9 | import org.antlr.v4.runtime.misc.NotNull; 10 | 11 | /** 12 | * Created by KevinOfNeu on 2018/8/31 12:24. 13 | */ 14 | public class IfStatementVisitor extends EnkelBaseVisitor { 15 | private final StatementVisitor statementVisitor; 16 | private final ExpressionVisitor expressionVisitor; 17 | public IfStatementVisitor(StatementVisitor statementVisitor, ExpressionVisitor expressionVisitor) { 18 | this.statementVisitor = statementVisitor; 19 | this.expressionVisitor = expressionVisitor; 20 | } 21 | @Override 22 | public IfStatement visitIfStatement(@NotNull EnkelParser.IfStatementContext ctx) { 23 | EnkelParser.ExpressionContext conditionalExpressionContext = ctx.expression(); 24 | Expression condition = conditionalExpressionContext.accept(expressionVisitor); 25 | Statement trueStatement = ctx.trueStatement.accept(statementVisitor); 26 | if (ctx.falseStatement != null) { 27 | Statement falseStatement = ctx.falseStatement.accept(statementVisitor); 28 | return new IfStatement(condition, trueStatement, falseStatement); 29 | } 30 | return new IfStatement(condition, trueStatement); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /compiler/src/main/java/com/bendcap/enkel/compiler/parsing/visitor/statement/PrintStatementVisitor.java: -------------------------------------------------------------------------------- 1 | package com.bendcap.enkel.compiler.parsing.visitor.statement; 2 | 3 | import com.bendcap.enkel.antlr.EnkelBaseVisitor; 4 | import com.bendcap.enkel.antlr.EnkelParser; 5 | import com.bendcap.enkel.compiler.domain.node.expression.Expression; 6 | import com.bendcap.enkel.compiler.domain.node.statement.PrintStatement; 7 | import com.bendcap.enkel.compiler.parsing.visitor.expression.ExpressionVisitor; 8 | import org.antlr.v4.runtime.misc.NotNull; 9 | 10 | /** 11 | * Created by KevinOfNeu on 2018/8/31 12:25. 12 | */ 13 | public class PrintStatementVisitor extends EnkelBaseVisitor { 14 | private final ExpressionVisitor expressionVisitor; 15 | public PrintStatementVisitor(ExpressionVisitor expressionVisitor) { 16 | this.expressionVisitor = expressionVisitor; 17 | } 18 | @Override 19 | public PrintStatement visitPrintStatement(@NotNull EnkelParser.PrintStatementContext ctx) { 20 | EnkelParser.ExpressionContext expressionCtx = ctx.expression(); 21 | Expression expression = expressionCtx.accept(expressionVisitor); 22 | return new PrintStatement(expression); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /compiler/src/main/java/com/bendcap/enkel/compiler/parsing/visitor/statement/ReturnStatementVisitor.java: -------------------------------------------------------------------------------- 1 | package com.bendcap.enkel.compiler.parsing.visitor.statement; 2 | 3 | import com.bendcap.enkel.antlr.EnkelBaseVisitor; 4 | import com.bendcap.enkel.antlr.EnkelParser; 5 | import com.bendcap.enkel.compiler.domain.node.expression.EmptyExpression; 6 | import com.bendcap.enkel.compiler.domain.node.expression.Expression; 7 | import com.bendcap.enkel.compiler.domain.node.statement.ReturnStatement; 8 | import com.bendcap.enkel.compiler.domain.type.BultInType; 9 | import com.bendcap.enkel.compiler.parsing.visitor.expression.ExpressionVisitor; 10 | import org.antlr.v4.runtime.misc.NotNull; 11 | 12 | /** 13 | * Created by KevinOfNeu on 2018/8/31 12:25. 14 | */ 15 | public class ReturnStatementVisitor extends EnkelBaseVisitor { 16 | private final ExpressionVisitor expressionVisitor; 17 | public ReturnStatementVisitor(ExpressionVisitor expressionVisitor) { 18 | this.expressionVisitor = expressionVisitor; 19 | } 20 | @Override 21 | public ReturnStatement visitReturnVoid(@NotNull EnkelParser.ReturnVoidContext ctx) { 22 | return new ReturnStatement(new EmptyExpression(BultInType.VOID)); 23 | } 24 | @Override 25 | public ReturnStatement visitReturnWithValue(@NotNull EnkelParser.ReturnWithValueContext ctx) { 26 | Expression expression = ctx.expression().accept(expressionVisitor); 27 | return new ReturnStatement(expression); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /compiler/src/main/java/com/bendcap/enkel/compiler/parsing/visitor/statement/StatementVisitor.java: -------------------------------------------------------------------------------- 1 | package com.bendcap.enkel.compiler.parsing.visitor.statement; 2 | 3 | import com.bendcap.enkel.antlr.EnkelBaseVisitor; 4 | import com.bendcap.enkel.antlr.EnkelParser; 5 | import com.bendcap.enkel.compiler.domain.node.expression.ConditionalExpression; 6 | import com.bendcap.enkel.compiler.domain.node.expression.Expression; 7 | import com.bendcap.enkel.compiler.domain.node.statement.Statement; 8 | import com.bendcap.enkel.compiler.domain.scope.Scope; 9 | import com.bendcap.enkel.compiler.parsing.visitor.expression.ExpressionVisitor; 10 | import org.antlr.v4.runtime.misc.NotNull; 11 | 12 | /** 13 | * Created by KevinOfNeu on 2018/8/31 12:25. 14 | */ 15 | public class StatementVisitor extends EnkelBaseVisitor { 16 | private final ExpressionVisitor expressionVisitor; 17 | private final PrintStatementVisitor printStatementVisitor; 18 | private final VariableDeclarationStatementVisitor variableDeclarationStatementVisitor; 19 | private final ReturnStatementVisitor returnStatementVisitor; 20 | private final BlockStatementVisitor blockStatementVisitor; 21 | private final IfStatementVisitor ifStatementVisitor; 22 | private final ForStatementVisitor forStatementVisitor; 23 | private final AssignmentStatementVisitor assignmentStatementVisitor; 24 | 25 | public StatementVisitor(Scope scope) { 26 | expressionVisitor = new ExpressionVisitor(scope); 27 | printStatementVisitor = new PrintStatementVisitor(expressionVisitor); 28 | variableDeclarationStatementVisitor = new VariableDeclarationStatementVisitor(expressionVisitor, scope); 29 | returnStatementVisitor = new ReturnStatementVisitor(expressionVisitor); 30 | blockStatementVisitor = new BlockStatementVisitor(scope); 31 | ifStatementVisitor = new IfStatementVisitor(this, expressionVisitor); 32 | forStatementVisitor = new ForStatementVisitor(scope); 33 | assignmentStatementVisitor = new AssignmentStatementVisitor(expressionVisitor); 34 | } 35 | 36 | @Override 37 | public Statement visitPrintStatement(@NotNull EnkelParser.PrintStatementContext ctx) { 38 | return printStatementVisitor.visitPrintStatement(ctx); 39 | } 40 | 41 | @Override 42 | public Statement visitVariableDeclaration(@NotNull EnkelParser.VariableDeclarationContext ctx) { 43 | return variableDeclarationStatementVisitor.visitVariableDeclaration(ctx); 44 | } 45 | 46 | @Override 47 | public Statement visitReturnVoid(@NotNull EnkelParser.ReturnVoidContext ctx) { 48 | return returnStatementVisitor.visitReturnVoid(ctx); 49 | } 50 | 51 | @Override 52 | public Statement visitReturnWithValue(@NotNull EnkelParser.ReturnWithValueContext ctx) { 53 | return returnStatementVisitor.visitReturnWithValue(ctx); 54 | } 55 | 56 | @Override 57 | public Statement visitBlock(@NotNull EnkelParser.BlockContext ctx) { 58 | return blockStatementVisitor.visitBlock(ctx); 59 | } 60 | 61 | @Override 62 | public Statement visitIfStatement(@NotNull EnkelParser.IfStatementContext ctx) { 63 | return ifStatementVisitor.visitIfStatement(ctx); 64 | } 65 | 66 | @Override 67 | public Expression visitVarReference(@NotNull EnkelParser.VarReferenceContext ctx) { 68 | return expressionVisitor.visitVarReference(ctx); 69 | } 70 | 71 | @Override 72 | public Expression visitValue(@NotNull EnkelParser.ValueContext ctx) { 73 | return expressionVisitor.visitValue(ctx); 74 | } 75 | 76 | @Override 77 | public Expression visitFunctionCall(@NotNull EnkelParser.FunctionCallContext ctx) { 78 | return expressionVisitor.visitFunctionCall(ctx); 79 | } 80 | 81 | @Override 82 | public Expression visitConstructorCall(@NotNull EnkelParser.ConstructorCallContext ctx) { 83 | return expressionVisitor.visitConstructorCall(ctx); 84 | } 85 | 86 | @Override 87 | public Expression visitSupercall(@NotNull EnkelParser.SupercallContext ctx) { 88 | return expressionVisitor.visitSupercall(ctx); 89 | } 90 | 91 | @Override 92 | public Expression visitAdd(@NotNull EnkelParser.AddContext ctx) { 93 | return expressionVisitor.visitAdd(ctx); 94 | } 95 | 96 | @Override 97 | public Expression visitMultiply(@NotNull EnkelParser.MultiplyContext ctx) { 98 | return expressionVisitor.visitMultiply(ctx); 99 | } 100 | 101 | @Override 102 | public Expression visitSubstract(@NotNull EnkelParser.SubstractContext ctx) { 103 | return expressionVisitor.visitSubstract(ctx); 104 | } 105 | 106 | @Override 107 | public Expression visitDivide(@NotNull EnkelParser.DivideContext ctx) { 108 | return expressionVisitor.visitDivide(ctx); 109 | } 110 | 111 | @Override 112 | public ConditionalExpression visitConditionalExpression(@NotNull EnkelParser.ConditionalExpressionContext ctx) { 113 | return expressionVisitor.visitConditionalExpression(ctx); 114 | } 115 | 116 | @Override 117 | public Statement visitForStatement(@NotNull EnkelParser.ForStatementContext ctx) { 118 | return forStatementVisitor.visitForStatement(ctx); 119 | } 120 | 121 | @Override 122 | public Statement visitAssignment(EnkelParser.AssignmentContext ctx) { 123 | return assignmentStatementVisitor.visitAssignment(ctx); 124 | } 125 | } 126 | -------------------------------------------------------------------------------- /compiler/src/main/java/com/bendcap/enkel/compiler/parsing/visitor/statement/VariableDeclarationStatementVisitor.java: -------------------------------------------------------------------------------- 1 | package com.bendcap.enkel.compiler.parsing.visitor.statement; 2 | 3 | import com.bendcap.enkel.antlr.EnkelBaseVisitor; 4 | import com.bendcap.enkel.antlr.EnkelParser; 5 | import com.bendcap.enkel.compiler.domain.node.expression.Expression; 6 | import com.bendcap.enkel.compiler.domain.node.statement.VariableDeclaration; 7 | import com.bendcap.enkel.compiler.domain.scope.LocalVariable; 8 | import com.bendcap.enkel.compiler.domain.scope.Scope; 9 | import com.bendcap.enkel.compiler.parsing.visitor.expression.ExpressionVisitor; 10 | import org.antlr.v4.runtime.misc.NotNull; 11 | 12 | /** 13 | * Created by KevinOfNeu on 2018/8/31 12:26. 14 | */ 15 | public class VariableDeclarationStatementVisitor extends EnkelBaseVisitor { 16 | private final ExpressionVisitor expressionVisitor; 17 | private final Scope scope; 18 | public VariableDeclarationStatementVisitor(ExpressionVisitor expressionVisitor, Scope scope) { 19 | this.expressionVisitor = expressionVisitor; 20 | this.scope = scope; 21 | } 22 | @Override 23 | public VariableDeclaration visitVariableDeclaration(@NotNull EnkelParser.VariableDeclarationContext ctx) { 24 | String varName = ctx.name().getText(); 25 | EnkelParser.ExpressionContext expressionCtx = ctx.expression(); 26 | Expression expression = expressionCtx.accept(expressionVisitor); 27 | scope.addLocalVariable(new LocalVariable(varName, expression.getType())); 28 | return new VariableDeclaration(varName, expression); 29 | } 30 | } 31 | 32 | -------------------------------------------------------------------------------- /compiler/src/main/java/com/bendcap/enkel/compiler/utils/DescriptorFactory.java: -------------------------------------------------------------------------------- 1 | package com.bendcap.enkel.compiler.utils; 2 | 3 | import com.bendcap.enkel.compiler.domain.Function; 4 | import com.bendcap.enkel.compiler.domain.node.expression.Parameter; 5 | import com.bendcap.enkel.compiler.domain.scope.FunctionSignature; 6 | import com.bendcap.enkel.compiler.domain.type.Type; 7 | 8 | import java.util.Collection; 9 | import java.util.stream.Collectors; 10 | 11 | /** 12 | * Created by KevinOfNeu on 2018/8/22 14:57. 13 | */ 14 | public class DescriptorFactory { 15 | 16 | public static String getMethodDescriptor(Function function) { 17 | Collection parameters = function.getParameters(); 18 | Type returnType = function.getReturnType(); 19 | return getMethodDescriptor(parameters, returnType); 20 | } 21 | 22 | public static String getMethodDescriptor(FunctionSignature signature) { 23 | Collection parameters = signature.getParameters(); 24 | Type returnType = signature.getReturnType(); 25 | return getMethodDescriptor(parameters, returnType); 26 | } 27 | 28 | private static String getMethodDescriptor(Collection parameters, Type returnType) { 29 | String parametersDescriptor = parameters.stream() 30 | .map(parameter -> parameter.getType().getDescriptor()) 31 | .collect(Collectors.joining("", "(", ")")); 32 | String returnDescriptor = returnType.getDescriptor(); 33 | return parametersDescriptor + returnDescriptor; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /compiler/src/main/java/com/bendcap/enkel/compiler/utils/PrimitiveTypesWrapperFactory.java: -------------------------------------------------------------------------------- 1 | package com.bendcap.enkel.compiler.utils; 2 | 3 | import com.bendcap.enkel.compiler.domain.type.BultInType; 4 | import com.bendcap.enkel.compiler.domain.type.ClassType; 5 | import com.bendcap.enkel.compiler.domain.type.Type; 6 | import com.google.common.collect.BiMap; 7 | import com.google.common.collect.ImmutableBiMap; 8 | import com.google.common.collect.ImmutableMap; 9 | 10 | import java.util.Map; 11 | import java.util.Optional; 12 | 13 | /** 14 | * Created by KevinOfNeu on 2018/9/1 23:09. 15 | */ 16 | public class PrimitiveTypesWrapperFactory { 17 | private final static BiMap types = ImmutableBiMap.of( 18 | BultInType.INT, ClassType.Integer(), 19 | BultInType.BOOLEAN, ClassType.Boolean(), 20 | BultInType.FLOAT, ClassType.Float(), 21 | BultInType.DOUBLE, ClassType.Double() 22 | ); 23 | private final static Map toPrimitiveMethodName = ImmutableMap.of( 24 | ClassType.Integer(), "intValue" 25 | ); 26 | 27 | public static Optional getPrimitiveForWrapper(Type type) { 28 | return Optional.ofNullable(types.inverse().get(type)); 29 | } 30 | 31 | public static Optional getWrapperForPrimitive(Type type) { 32 | return Optional.ofNullable(types.get(type)); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /compiler/src/main/java/com/bendcap/enkel/compiler/utils/ReflectionObjectToSignatureMapper.java: -------------------------------------------------------------------------------- 1 | package com.bendcap.enkel.compiler.utils; 2 | 3 | import com.bendcap.enkel.compiler.domain.node.expression.Parameter; 4 | import com.bendcap.enkel.compiler.domain.scope.FunctionSignature; 5 | import com.bendcap.enkel.compiler.domain.type.BultInType; 6 | 7 | import java.lang.reflect.Constructor; 8 | import java.lang.reflect.Method; 9 | import java.util.Arrays; 10 | import java.util.List; 11 | import java.util.Optional; 12 | 13 | import static java.util.stream.Collectors.toList; 14 | 15 | /** 16 | * Created by KevinOfNeu on 2018/8/30 16:07. 17 | */ 18 | public final class ReflectionObjectToSignatureMapper { 19 | public static FunctionSignature fromMethod(Method method) { 20 | String name = method.getName(); 21 | List parameters = Arrays.stream(method.getParameters()) 22 | .map(p -> new Parameter(p.getName(), TypeResolver.getFromTypeName(p.getType().getCanonicalName()), Optional.empty())) 23 | .collect(toList()); 24 | Class returnType = method.getReturnType(); 25 | return new FunctionSignature(name, parameters, TypeResolver.getFromTypeName(returnType.getCanonicalName())); 26 | } 27 | 28 | public static FunctionSignature fromConstructor(Constructor constructor) { 29 | String name = constructor.getName(); 30 | List parameters = Arrays.stream(constructor.getParameters()) 31 | .map(p -> new Parameter(p.getName(), TypeResolver.getFromTypeName(p.getType().getCanonicalName()), Optional.empty())) 32 | .collect(toList()); 33 | return new FunctionSignature(name, parameters, BultInType.VOID); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /compiler/src/main/java/com/bendcap/enkel/compiler/utils/TypeChecker.java: -------------------------------------------------------------------------------- 1 | package com.bendcap.enkel.compiler.utils; 2 | 3 | import com.bendcap.enkel.compiler.domain.type.BultInType; 4 | import com.bendcap.enkel.compiler.domain.type.Type; 5 | 6 | /** 7 | * Created by KevinOfNeu on 2018/8/29 23:45. 8 | */ 9 | public class TypeChecker { 10 | public static boolean isInt(Type type) { 11 | return type == BultInType.INT; 12 | } 13 | 14 | public static boolean isBool(Type type) { 15 | return type == BultInType.BOOLEAN; 16 | } 17 | 18 | public static boolean isFloat(Type type) { 19 | return type == BultInType.FLOAT; 20 | } 21 | 22 | public static boolean isDouble(Type type) { 23 | return type == BultInType.DOUBLE; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /compiler/src/main/java/com/bendcap/enkel/compiler/utils/TypeResolver.java: -------------------------------------------------------------------------------- 1 | package com.bendcap.enkel.compiler.utils; 2 | 3 | import com.bendcap.enkel.antlr.EnkelParser; 4 | import com.bendcap.enkel.compiler.domain.type.BultInType; 5 | import com.bendcap.enkel.compiler.domain.type.ClassType; 6 | import com.bendcap.enkel.compiler.domain.type.Type; 7 | import com.google.common.primitives.Doubles; 8 | import com.google.common.primitives.Floats; 9 | import com.google.common.primitives.Ints; 10 | import org.apache.commons.lang3.BooleanUtils; 11 | import org.apache.commons.lang3.StringUtils; 12 | import org.apache.commons.lang3.math.NumberUtils; 13 | 14 | import java.util.Arrays; 15 | import java.util.Optional; 16 | 17 | /** 18 | * Created by KevinOfNeu on 2018/8/22 11:00. 19 | */ 20 | public final class TypeResolver { 21 | 22 | public static Type getFromTypeContext(EnkelParser.TypeContext typeContext) { 23 | if(typeContext == null) return BultInType.VOID; 24 | return getFromTypeName(typeContext.getText()); 25 | } 26 | 27 | 28 | public static Type getFromTypeName(String typeName) { 29 | if(typeName.equals("java.lang.String")) return BultInType.STRING; 30 | Optional builtInType = getBuiltInType(typeName); 31 | if(builtInType.isPresent()) return builtInType.get(); 32 | return new ClassType(typeName); 33 | } 34 | 35 | public static Type getFromValue(EnkelParser.ValueContext value) { 36 | String stringValue = value.getText(); 37 | if (StringUtils.isEmpty(stringValue)) return BultInType.VOID; 38 | if (value.NUMBER() != null) { 39 | if (Ints.tryParse(stringValue) != null) { 40 | return BultInType.INT; 41 | } else if(Floats.tryParse(stringValue) != null) { 42 | return BultInType.FLOAT; 43 | } else if(Doubles.tryParse(stringValue) != null) { 44 | return BultInType.DOUBLE; 45 | } 46 | } else if (value.BOOL() != null) { 47 | return BultInType.BOOLEAN; 48 | } 49 | return BultInType.STRING; 50 | } 51 | 52 | public static Object getValueFromString(String stringValue, Type type) { 53 | if (TypeChecker.isInt(type)) { 54 | return Integer.valueOf(stringValue); 55 | } 56 | if (TypeChecker.isFloat(type)) { 57 | return Float.valueOf(stringValue); 58 | } 59 | if (TypeChecker.isDouble(type)) { 60 | return Double.valueOf(stringValue); 61 | } 62 | if (TypeChecker.isBool(type)) { 63 | return Boolean.valueOf(stringValue); 64 | } 65 | if (type == BultInType.STRING) { 66 | stringValue = StringUtils.removeStart(stringValue, "\""); 67 | stringValue = StringUtils.removeEnd(stringValue, "\""); 68 | return stringValue; 69 | } 70 | throw new AssertionError("Objects not yet implemented!"); 71 | } 72 | 73 | private static Optional getBuiltInType(String typeName) { 74 | return Arrays.stream(BultInType.values()) 75 | .filter(type -> type.getName().equals(typeName)) 76 | .findFirst(); 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /compiler/src/main/java/com/bendcap/enkel/compiler/validation/ARGUMENT_ERRORS.java: -------------------------------------------------------------------------------- 1 | package com.bendcap.enkel.compiler.validation; 2 | 3 | /** 4 | * Created by KevinOfNeu on 2018/7/18 21:14. 5 | */ 6 | public enum ARGUMENT_ERRORS { 7 | NONE(""), 8 | NO_FILE("Specify files for compilation"), 9 | BAD_FILE_EXTENSION("File has to end with .enk extension"); 10 | 11 | private String message; 12 | 13 | ARGUMENT_ERRORS(String message) { 14 | this.message = message; 15 | } 16 | 17 | public String getMessage() { 18 | return message; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | GROUP = com.bendcap.enkel 2 | VERSION = 1.0.0-SNAPSHOT -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KevinOfNeu/Enkel/9effaca2dc5c5cffe9b75fbefb83d028d702a611/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Thu Aug 23 23:23:08 CST 2018 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-all.zip 7 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Attempt to set APP_HOME 10 | # Resolve links: $0 may be a link 11 | PRG="$0" 12 | # Need this for relative symlinks. 13 | while [ -h "$PRG" ] ; do 14 | ls=`ls -ld "$PRG"` 15 | link=`expr "$ls" : '.*-> \(.*\)$'` 16 | if expr "$link" : '/.*' > /dev/null; then 17 | PRG="$link" 18 | else 19 | PRG=`dirname "$PRG"`"/$link" 20 | fi 21 | done 22 | SAVED="`pwd`" 23 | cd "`dirname \"$PRG\"`/" >/dev/null 24 | APP_HOME="`pwd -P`" 25 | cd "$SAVED" >/dev/null 26 | 27 | APP_NAME="Gradle" 28 | APP_BASE_NAME=`basename "$0"` 29 | 30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 31 | DEFAULT_JVM_OPTS="" 32 | 33 | # Use the maximum available, or set MAX_FD != -1 to use that value. 34 | MAX_FD="maximum" 35 | 36 | warn ( ) { 37 | echo "$*" 38 | } 39 | 40 | die ( ) { 41 | echo 42 | echo "$*" 43 | echo 44 | exit 1 45 | } 46 | 47 | # OS specific support (must be 'true' or 'false'). 48 | cygwin=false 49 | msys=false 50 | darwin=false 51 | nonstop=false 52 | case "`uname`" in 53 | CYGWIN* ) 54 | cygwin=true 55 | ;; 56 | Darwin* ) 57 | darwin=true 58 | ;; 59 | MINGW* ) 60 | msys=true 61 | ;; 62 | NONSTOP* ) 63 | nonstop=true 64 | ;; 65 | esac 66 | 67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 68 | 69 | # Determine the Java command to use to start the JVM. 70 | if [ -n "$JAVA_HOME" ] ; then 71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 72 | # IBM's JDK on AIX uses strange locations for the executables 73 | JAVACMD="$JAVA_HOME/jre/sh/java" 74 | else 75 | JAVACMD="$JAVA_HOME/bin/java" 76 | fi 77 | if [ ! -x "$JAVACMD" ] ; then 78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 79 | 80 | Please set the JAVA_HOME variable in your environment to match the 81 | location of your Java installation." 82 | fi 83 | else 84 | JAVACMD="java" 85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 86 | 87 | Please set the JAVA_HOME variable in your environment to match the 88 | location of your Java installation." 89 | fi 90 | 91 | # Increase the maximum file descriptors if we can. 92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then 93 | MAX_FD_LIMIT=`ulimit -H -n` 94 | if [ $? -eq 0 ] ; then 95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 96 | MAX_FD="$MAX_FD_LIMIT" 97 | fi 98 | ulimit -n $MAX_FD 99 | if [ $? -ne 0 ] ; then 100 | warn "Could not set maximum file descriptor limit: $MAX_FD" 101 | fi 102 | else 103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 104 | fi 105 | fi 106 | 107 | # For Darwin, add options to specify how the application appears in the dock 108 | if $darwin; then 109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 110 | fi 111 | 112 | # For Cygwin, switch paths to Windows format before running java 113 | if $cygwin ; then 114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 116 | JAVACMD=`cygpath --unix "$JAVACMD"` 117 | 118 | # We build the pattern for arguments to be converted via cygpath 119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 120 | SEP="" 121 | for dir in $ROOTDIRSRAW ; do 122 | ROOTDIRS="$ROOTDIRS$SEP$dir" 123 | SEP="|" 124 | done 125 | OURCYGPATTERN="(^($ROOTDIRS))" 126 | # Add a user-defined pattern to the cygpath arguments 127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 129 | fi 130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 131 | i=0 132 | for arg in "$@" ; do 133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 135 | 136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 138 | else 139 | eval `echo args$i`="\"$arg\"" 140 | fi 141 | i=$((i+1)) 142 | done 143 | case $i in 144 | (0) set -- ;; 145 | (1) set -- "$args0" ;; 146 | (2) set -- "$args0" "$args1" ;; 147 | (3) set -- "$args0" "$args1" "$args2" ;; 148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 154 | esac 155 | fi 156 | 157 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules 158 | function splitJvmOpts() { 159 | JVM_OPTS=("$@") 160 | } 161 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS 162 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" 163 | 164 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" 165 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | set DIRNAME=%~dp0 12 | if "%DIRNAME%" == "" set DIRNAME=. 13 | set APP_BASE_NAME=%~n0 14 | set APP_HOME=%DIRNAME% 15 | 16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 17 | set DEFAULT_JVM_OPTS= 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windows variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | if "%@eval[2+2]" == "4" goto 4NT_args 53 | 54 | :win9xME_args 55 | @rem Slurp the command line arguments. 56 | set CMD_LINE_ARGS= 57 | set _SKIP=2 58 | 59 | :win9xME_args_slurp 60 | if "x%~1" == "x" goto execute 61 | 62 | set CMD_LINE_ARGS=%* 63 | goto execute 64 | 65 | :4NT_args 66 | @rem Get arguments from the 4NT Shell from JP Software 67 | set CMD_LINE_ARGS=%$ 68 | 69 | :execute 70 | @rem Setup the command line 71 | 72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if "%ERRORLEVEL%"=="0" goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 85 | exit /b 1 86 | 87 | :mainEnd 88 | if "%OS%"=="Windows_NT" endlocal 89 | 90 | :omega 91 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'enkel' 2 | 3 | include "antlr" 4 | include "compiler" --------------------------------------------------------------------------------