├── .gitignore ├── compiler ├── .idea │ ├── artifacts │ │ ├── cka_jar.xml │ │ ├── ckc_jar.xml │ │ └── util.xml │ ├── codeStyles │ │ ├── Project.xml │ │ └── codeStyleConfig.xml │ ├── encodings.xml │ ├── kotlinc.xml │ ├── libraries │ │ ├── KotlinJavaRuntime.xml │ │ ├── antlr4_runtime_4_7_2.xml │ │ └── commons_cli_1_4.xml │ ├── misc.xml │ ├── modules.xml │ ├── uiDesigner.xml │ └── vcs.xml ├── cka │ ├── cka.iml │ ├── gen │ │ ├── cka.interp │ │ ├── cka.tokens │ │ ├── ckaBaseListener.java │ │ ├── ckaBaseVisitor.java │ │ ├── ckaLexer.interp │ │ ├── ckaLexer.java │ │ ├── ckaLexer.tokens │ │ ├── ckaListener.java │ │ ├── ckaParser.java │ │ └── ckaVisitor.java │ ├── grammar │ │ └── cka.g4 │ └── src │ │ ├── Cli.kt │ │ ├── FileVisitor.kt │ │ ├── Function.kt │ │ ├── Instruction.kt │ │ ├── META-INF │ │ └── MANIFEST.MF │ │ ├── Main.kt │ │ ├── Opcode.kt │ │ ├── OutputContext.kt │ │ └── ParseContext.kt ├── ckc │ ├── ckc.iml │ ├── gen │ │ ├── ck.interp │ │ ├── ck.tokens │ │ ├── ckBaseListener.java │ │ ├── ckBaseVisitor.java │ │ ├── ckLexer.interp │ │ ├── ckLexer.java │ │ ├── ckLexer.tokens │ │ ├── ckListener.java │ │ ├── ckParser.java │ │ └── ckVisitor.java │ ├── grammar │ │ └── ck.g4 │ ├── src │ │ ├── META-INF │ │ │ └── MANIFEST.MF │ │ └── ck │ │ │ ├── Cli.kt │ │ │ ├── Main.kt │ │ │ ├── analyze │ │ │ └── Analyze.kt │ │ │ ├── ast │ │ │ ├── Type.kt │ │ │ ├── node │ │ │ │ ├── ASTNode.kt │ │ │ │ ├── CkFile.kt │ │ │ │ ├── Decl.kt │ │ │ │ └── Expr.kt │ │ │ └── visitors │ │ │ │ ├── ASTVisitor.kt │ │ │ │ ├── CompilationVisitor.kt │ │ │ │ ├── ComputeCapturesVisitor.kt │ │ │ │ ├── FindTailCalls.kt │ │ │ │ ├── GetDefinitionVisitor.kt │ │ │ │ ├── GetEnclosingFunction.kt │ │ │ │ └── ScopeLinkingVisitor.kt │ │ │ ├── compiler │ │ │ └── StackFrame.kt │ │ │ └── grammar │ │ │ ├── Parse.kt │ │ │ └── visitors │ │ │ ├── DeclVisitor.kt │ │ │ ├── ExprVisitor.kt │ │ │ ├── ExprsVisitor.kt │ │ │ ├── FileVisitor.kt │ │ │ ├── SequenceVisitor.kt │ │ │ ├── TypeVisitor.kt │ │ │ └── TypesVisitor.kt │ └── test │ │ ├── AnalyzeTest.kt │ │ ├── CompilationVisitorTest.kt │ │ └── ParseTest.kt ├── compiler.iml ├── lib │ ├── antlr4-runtime-4.7.2.jar │ ├── apiguardian-api-1.0.0.jar │ ├── commons-cli-1.4.jar │ ├── hamcrest-all-1.3.jar │ ├── junit-4.13-beta-2.jar │ ├── junit-jupiter-api-5.4.1.jar │ ├── junit-jupiter-api-5.5.0-M1.jar │ ├── junit-platform-commons-1.4.1.jar │ ├── junit-platform-commons-1.5.0-M1.jar │ ├── kotlin-reflect-sources.jar │ ├── kotlin-reflect.jar │ ├── kotlin-stdlib-jdk7-sources.jar │ ├── kotlin-stdlib-jdk7.jar │ ├── kotlin-stdlib-jdk8-sources.jar │ ├── kotlin-stdlib-jdk8.jar │ ├── kotlin-stdlib-sources.jar │ ├── kotlin-stdlib.jar │ ├── kotlin-test-sources.jar │ ├── kotlin-test.jar │ └── opentest4j-1.1.1.jar ├── out │ └── artifacts │ │ ├── cka_jar │ │ └── cka.jar │ │ └── ckc_jar │ │ └── ckc.jar └── util │ ├── src │ └── util │ │ ├── antlr │ │ └── ThrowingErrorListener.kt │ │ ├── either │ │ └── Either.kt │ │ └── extensions │ │ └── Extensions.kt │ ├── test │ └── util │ │ └── either │ │ └── EitherTest.kt │ └── util.iml ├── example ├── ADT.ck ├── cons.ck ├── either.ck ├── even.ck ├── fact.ck ├── howToCompileModules.txt ├── id.ck ├── id2.ck ├── simple.ck └── simple │ ├── makefile │ └── simple_io.ck ├── readme.md └── runtime ├── bitmap.h ├── builtin_cfuns.c ├── c_static_assert.h ├── copying_gc.c ├── copying_gc.h ├── gc_interface.h ├── incremental_copying.ods ├── incremental_copying_gc_pseudo_code.txt ├── incremental_gc.c ├── incremental_gc.h ├── mark_compact_gc.c ├── mark_compact_gc.h ├── test ├── bitmap │ └── test_bitmap.c ├── gc │ ├── makefile │ ├── test │ └── test_gc.c ├── incremental_gc │ ├── incremental_gc_test.c │ ├── incremental_gc_test.h │ ├── incremental_gc_test_sln │ │ ├── incremental_gc_test │ │ │ ├── incremental_gc_test.vcxproj │ │ │ ├── incremental_gc_test.vcxproj.filters │ │ │ └── main.cpp │ │ └── incremental_gc_test_sln.sln │ ├── makefile │ ├── test │ └── test_gc.c ├── mark_compact_gc │ ├── makefile │ ├── test │ └── test_gc.c └── vm │ ├── makefile │ └── test_vm.c ├── timer.h └── vm.h /.gitignore: -------------------------------------------------------------------------------- 1 | *.exe 2 | *.o 3 | *.elf 4 | *.hex 5 | *.eep 6 | **/Debug/** 7 | **/Release/** 8 | **/out/** 9 | .DS_Store 10 | */.DS_Store 11 | **/.vs/** 12 | *.vcxproj.user 13 | workspace.xml -------------------------------------------------------------------------------- /compiler/.idea/artifacts/cka_jar.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | $PROJECT_DIR$/out/artifacts/cka_jar 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /compiler/.idea/artifacts/ckc_jar.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | $PROJECT_DIR$/out/artifacts/ckc_jar 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /compiler/.idea/artifacts/util.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | $PROJECT_DIR$/out/artifacts/util 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /compiler/.idea/codeStyles/Project.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /compiler/.idea/codeStyles/codeStyleConfig.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | -------------------------------------------------------------------------------- /compiler/.idea/encodings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /compiler/.idea/kotlinc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 10 | -------------------------------------------------------------------------------- /compiler/.idea/libraries/KotlinJavaRuntime.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /compiler/.idea/libraries/antlr4_runtime_4_7_2.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /compiler/.idea/libraries/commons_cli_1_4.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /compiler/.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /compiler/.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /compiler/.idea/uiDesigner.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | -------------------------------------------------------------------------------- /compiler/.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /compiler/cka/cka.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /compiler/cka/gen/cka.interp: -------------------------------------------------------------------------------- 1 | token literal names: 2 | null 3 | ':' 4 | 'layout' 5 | 'alloc' 6 | 'ncall' 7 | 'push' 8 | 'jump' 9 | 'jumpz' 10 | 'jumpnz' 11 | 'aload' 12 | 'astore' 13 | 'lload' 14 | 'lstore' 15 | 'rload' 16 | 'rstore' 17 | 'cload' 18 | 'cstore' 19 | 'debugpush' 20 | 'add' 21 | 'sub' 22 | 'mul' 23 | 'div' 24 | 'mod' 25 | 'shl' 26 | 'shr' 27 | 'neg' 28 | 'not' 29 | 'bitnot' 30 | 'bitand' 31 | 'bitxor' 32 | 'bitor' 33 | 'lt' 34 | 'lte' 35 | 'gt' 36 | 'gte' 37 | 'eq' 38 | 'neq' 39 | 'cmp' 40 | 'call' 41 | 'return' 42 | 'dup' 43 | 'pop' 44 | 'swap' 45 | 'enter' 46 | 'leave' 47 | 'nop' 48 | 'halt' 49 | 'load' 50 | 'store' 51 | 'rbarrier' 52 | 'wbarrier' 53 | 'debugpop' 54 | 'clear' 55 | 'goto' 56 | '[' 57 | ']' 58 | ',' 59 | '*' 60 | '-' 61 | null 62 | null 63 | null 64 | null 65 | null 66 | null 67 | 68 | token symbolic names: 69 | null 70 | null 71 | null 72 | null 73 | null 74 | null 75 | null 76 | null 77 | null 78 | null 79 | null 80 | null 81 | null 82 | null 83 | null 84 | null 85 | null 86 | null 87 | null 88 | null 89 | null 90 | null 91 | null 92 | null 93 | null 94 | null 95 | null 96 | null 97 | null 98 | null 99 | null 100 | null 101 | null 102 | null 103 | null 104 | null 105 | null 106 | null 107 | null 108 | null 109 | null 110 | null 111 | null 112 | null 113 | null 114 | null 115 | null 116 | null 117 | null 118 | null 119 | null 120 | null 121 | null 122 | null 123 | null 124 | null 125 | null 126 | null 127 | null 128 | NATURAL 129 | ID 130 | LABEL 131 | STRING 132 | WHITESPACE 133 | COMMENT 134 | 135 | rule names: 136 | file 137 | instructions 138 | instruction 139 | literalLabelMnemonic 140 | literalIntMnemonic 141 | literalStringMnemonic 142 | simpleInstruction 143 | frameLayout 144 | allocLayout 145 | integer 146 | 147 | 148 | atn: 149 | [3, 24715, 42794, 33075, 47597, 16764, 15335, 30598, 22884, 3, 66, 99, 4, 2, 9, 2, 4, 3, 9, 3, 4, 4, 9, 4, 4, 5, 9, 5, 4, 6, 9, 6, 4, 7, 9, 7, 4, 8, 9, 8, 4, 9, 9, 9, 4, 10, 9, 10, 4, 11, 9, 11, 3, 2, 5, 2, 24, 10, 2, 3, 2, 3, 2, 3, 3, 3, 3, 7, 3, 30, 10, 3, 12, 3, 14, 3, 33, 11, 3, 3, 4, 3, 4, 3, 4, 3, 4, 3, 4, 3, 4, 3, 4, 3, 4, 3, 4, 3, 4, 3, 4, 3, 4, 3, 4, 3, 4, 3, 4, 3, 4, 3, 4, 3, 4, 5, 4, 53, 10, 4, 3, 5, 3, 5, 3, 6, 3, 6, 3, 7, 3, 7, 3, 8, 3, 8, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 7, 9, 69, 10, 9, 12, 9, 14, 9, 72, 11, 9, 3, 9, 5, 9, 75, 10, 9, 3, 10, 3, 10, 3, 10, 3, 10, 3, 10, 3, 10, 3, 10, 3, 10, 3, 10, 7, 10, 86, 10, 10, 12, 10, 14, 10, 89, 11, 10, 3, 10, 5, 10, 92, 10, 10, 3, 11, 5, 11, 95, 10, 11, 3, 11, 3, 11, 3, 11, 2, 2, 12, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 2, 5, 3, 2, 7, 10, 4, 2, 7, 7, 11, 18, 3, 2, 20, 55, 2, 103, 2, 23, 3, 2, 2, 2, 4, 27, 3, 2, 2, 2, 6, 52, 3, 2, 2, 2, 8, 54, 3, 2, 2, 2, 10, 56, 3, 2, 2, 2, 12, 58, 3, 2, 2, 2, 14, 60, 3, 2, 2, 2, 16, 74, 3, 2, 2, 2, 18, 91, 3, 2, 2, 2, 20, 94, 3, 2, 2, 2, 22, 24, 5, 4, 3, 2, 23, 22, 3, 2, 2, 2, 23, 24, 3, 2, 2, 2, 24, 25, 3, 2, 2, 2, 25, 26, 7, 2, 2, 3, 26, 3, 3, 2, 2, 2, 27, 31, 5, 6, 4, 2, 28, 30, 5, 6, 4, 2, 29, 28, 3, 2, 2, 2, 30, 33, 3, 2, 2, 2, 31, 29, 3, 2, 2, 2, 31, 32, 3, 2, 2, 2, 32, 5, 3, 2, 2, 2, 33, 31, 3, 2, 2, 2, 34, 35, 7, 63, 2, 2, 35, 53, 7, 3, 2, 2, 36, 53, 5, 14, 8, 2, 37, 38, 5, 10, 6, 2, 38, 39, 5, 20, 11, 2, 39, 53, 3, 2, 2, 2, 40, 41, 5, 8, 5, 2, 41, 42, 7, 63, 2, 2, 42, 53, 3, 2, 2, 2, 43, 44, 5, 12, 7, 2, 44, 45, 7, 64, 2, 2, 45, 53, 3, 2, 2, 2, 46, 47, 7, 4, 2, 2, 47, 53, 5, 16, 9, 2, 48, 49, 7, 5, 2, 2, 49, 53, 5, 18, 10, 2, 50, 51, 7, 6, 2, 2, 51, 53, 7, 62, 2, 2, 52, 34, 3, 2, 2, 2, 52, 36, 3, 2, 2, 2, 52, 37, 3, 2, 2, 2, 52, 40, 3, 2, 2, 2, 52, 43, 3, 2, 2, 2, 52, 46, 3, 2, 2, 2, 52, 48, 3, 2, 2, 2, 52, 50, 3, 2, 2, 2, 53, 7, 3, 2, 2, 2, 54, 55, 9, 2, 2, 2, 55, 9, 3, 2, 2, 2, 56, 57, 9, 3, 2, 2, 57, 11, 3, 2, 2, 2, 58, 59, 7, 19, 2, 2, 59, 13, 3, 2, 2, 2, 60, 61, 9, 4, 2, 2, 61, 15, 3, 2, 2, 2, 62, 63, 7, 56, 2, 2, 63, 75, 7, 57, 2, 2, 64, 65, 7, 56, 2, 2, 65, 70, 7, 61, 2, 2, 66, 67, 7, 58, 2, 2, 67, 69, 7, 61, 2, 2, 68, 66, 3, 2, 2, 2, 69, 72, 3, 2, 2, 2, 70, 68, 3, 2, 2, 2, 70, 71, 3, 2, 2, 2, 71, 73, 3, 2, 2, 2, 72, 70, 3, 2, 2, 2, 73, 75, 7, 57, 2, 2, 74, 62, 3, 2, 2, 2, 74, 64, 3, 2, 2, 2, 75, 17, 3, 2, 2, 2, 76, 77, 7, 56, 2, 2, 77, 78, 7, 59, 2, 2, 78, 92, 7, 57, 2, 2, 79, 80, 7, 56, 2, 2, 80, 92, 7, 57, 2, 2, 81, 82, 7, 56, 2, 2, 82, 87, 7, 61, 2, 2, 83, 84, 7, 58, 2, 2, 84, 86, 7, 61, 2, 2, 85, 83, 3, 2, 2, 2, 86, 89, 3, 2, 2, 2, 87, 85, 3, 2, 2, 2, 87, 88, 3, 2, 2, 2, 88, 90, 3, 2, 2, 2, 89, 87, 3, 2, 2, 2, 90, 92, 7, 57, 2, 2, 91, 76, 3, 2, 2, 2, 91, 79, 3, 2, 2, 2, 91, 81, 3, 2, 2, 2, 92, 19, 3, 2, 2, 2, 93, 95, 7, 60, 2, 2, 94, 93, 3, 2, 2, 2, 94, 95, 3, 2, 2, 2, 95, 96, 3, 2, 2, 2, 96, 97, 7, 61, 2, 2, 97, 21, 3, 2, 2, 2, 10, 23, 31, 52, 70, 74, 87, 91, 94] -------------------------------------------------------------------------------- /compiler/cka/gen/cka.tokens: -------------------------------------------------------------------------------- 1 | T__0=1 2 | T__1=2 3 | T__2=3 4 | T__3=4 5 | T__4=5 6 | T__5=6 7 | T__6=7 8 | T__7=8 9 | T__8=9 10 | T__9=10 11 | T__10=11 12 | T__11=12 13 | T__12=13 14 | T__13=14 15 | T__14=15 16 | T__15=16 17 | T__16=17 18 | T__17=18 19 | T__18=19 20 | T__19=20 21 | T__20=21 22 | T__21=22 23 | T__22=23 24 | T__23=24 25 | T__24=25 26 | T__25=26 27 | T__26=27 28 | T__27=28 29 | T__28=29 30 | T__29=30 31 | T__30=31 32 | T__31=32 33 | T__32=33 34 | T__33=34 35 | T__34=35 36 | T__35=36 37 | T__36=37 38 | T__37=38 39 | T__38=39 40 | T__39=40 41 | T__40=41 42 | T__41=42 43 | T__42=43 44 | T__43=44 45 | T__44=45 46 | T__45=46 47 | T__46=47 48 | T__47=48 49 | T__48=49 50 | T__49=50 51 | T__50=51 52 | T__51=52 53 | T__52=53 54 | T__53=54 55 | T__54=55 56 | T__55=56 57 | T__56=57 58 | T__57=58 59 | NATURAL=59 60 | ID=60 61 | LABEL=61 62 | STRING=62 63 | WHITESPACE=63 64 | COMMENT=64 65 | ':'=1 66 | 'layout'=2 67 | 'alloc'=3 68 | 'ncall'=4 69 | 'push'=5 70 | 'jump'=6 71 | 'jumpz'=7 72 | 'jumpnz'=8 73 | 'aload'=9 74 | 'astore'=10 75 | 'lload'=11 76 | 'lstore'=12 77 | 'rload'=13 78 | 'rstore'=14 79 | 'cload'=15 80 | 'cstore'=16 81 | 'debugpush'=17 82 | 'add'=18 83 | 'sub'=19 84 | 'mul'=20 85 | 'div'=21 86 | 'mod'=22 87 | 'shl'=23 88 | 'shr'=24 89 | 'neg'=25 90 | 'not'=26 91 | 'bitnot'=27 92 | 'bitand'=28 93 | 'bitxor'=29 94 | 'bitor'=30 95 | 'lt'=31 96 | 'lte'=32 97 | 'gt'=33 98 | 'gte'=34 99 | 'eq'=35 100 | 'neq'=36 101 | 'cmp'=37 102 | 'call'=38 103 | 'return'=39 104 | 'dup'=40 105 | 'pop'=41 106 | 'swap'=42 107 | 'enter'=43 108 | 'leave'=44 109 | 'nop'=45 110 | 'halt'=46 111 | 'load'=47 112 | 'store'=48 113 | 'rbarrier'=49 114 | 'wbarrier'=50 115 | 'debugpop'=51 116 | 'clear'=52 117 | 'goto'=53 118 | '['=54 119 | ']'=55 120 | ','=56 121 | '*'=57 122 | '-'=58 123 | -------------------------------------------------------------------------------- /compiler/cka/gen/ckaBaseListener.java: -------------------------------------------------------------------------------- 1 | // Generated from /Users/colinholzman/Documents/CopperKitten/compiler/cka/grammar/cka.g4 by ANTLR 4.7.2 2 | 3 | import org.antlr.v4.runtime.ParserRuleContext; 4 | import org.antlr.v4.runtime.tree.ErrorNode; 5 | import org.antlr.v4.runtime.tree.TerminalNode; 6 | 7 | /** 8 | * This class provides an empty implementation of {@link ckaListener}, 9 | * which can be extended to create a listener which only needs to handle a subset 10 | * of the available methods. 11 | */ 12 | public class ckaBaseListener implements ckaListener { 13 | /** 14 | * {@inheritDoc} 15 | * 16 | *

The default implementation does nothing.

17 | */ 18 | @Override public void enterFile(ckaParser.FileContext ctx) { } 19 | /** 20 | * {@inheritDoc} 21 | * 22 | *

The default implementation does nothing.

23 | */ 24 | @Override public void exitFile(ckaParser.FileContext ctx) { } 25 | /** 26 | * {@inheritDoc} 27 | * 28 | *

The default implementation does nothing.

29 | */ 30 | @Override public void enterInstructions(ckaParser.InstructionsContext ctx) { } 31 | /** 32 | * {@inheritDoc} 33 | * 34 | *

The default implementation does nothing.

35 | */ 36 | @Override public void exitInstructions(ckaParser.InstructionsContext ctx) { } 37 | /** 38 | * {@inheritDoc} 39 | * 40 | *

The default implementation does nothing.

41 | */ 42 | @Override public void enterLabelInst(ckaParser.LabelInstContext ctx) { } 43 | /** 44 | * {@inheritDoc} 45 | * 46 | *

The default implementation does nothing.

47 | */ 48 | @Override public void exitLabelInst(ckaParser.LabelInstContext ctx) { } 49 | /** 50 | * {@inheritDoc} 51 | * 52 | *

The default implementation does nothing.

53 | */ 54 | @Override public void enterSimpleInst(ckaParser.SimpleInstContext ctx) { } 55 | /** 56 | * {@inheritDoc} 57 | * 58 | *

The default implementation does nothing.

59 | */ 60 | @Override public void exitSimpleInst(ckaParser.SimpleInstContext ctx) { } 61 | /** 62 | * {@inheritDoc} 63 | * 64 | *

The default implementation does nothing.

65 | */ 66 | @Override public void enterLiteralIntInst(ckaParser.LiteralIntInstContext ctx) { } 67 | /** 68 | * {@inheritDoc} 69 | * 70 | *

The default implementation does nothing.

71 | */ 72 | @Override public void exitLiteralIntInst(ckaParser.LiteralIntInstContext ctx) { } 73 | /** 74 | * {@inheritDoc} 75 | * 76 | *

The default implementation does nothing.

77 | */ 78 | @Override public void enterLiteralLabelInst(ckaParser.LiteralLabelInstContext ctx) { } 79 | /** 80 | * {@inheritDoc} 81 | * 82 | *

The default implementation does nothing.

83 | */ 84 | @Override public void exitLiteralLabelInst(ckaParser.LiteralLabelInstContext ctx) { } 85 | /** 86 | * {@inheritDoc} 87 | * 88 | *

The default implementation does nothing.

89 | */ 90 | @Override public void enterLiteralStringInst(ckaParser.LiteralStringInstContext ctx) { } 91 | /** 92 | * {@inheritDoc} 93 | * 94 | *

The default implementation does nothing.

95 | */ 96 | @Override public void exitLiteralStringInst(ckaParser.LiteralStringInstContext ctx) { } 97 | /** 98 | * {@inheritDoc} 99 | * 100 | *

The default implementation does nothing.

101 | */ 102 | @Override public void enterLayoutInst(ckaParser.LayoutInstContext ctx) { } 103 | /** 104 | * {@inheritDoc} 105 | * 106 | *

The default implementation does nothing.

107 | */ 108 | @Override public void exitLayoutInst(ckaParser.LayoutInstContext ctx) { } 109 | /** 110 | * {@inheritDoc} 111 | * 112 | *

The default implementation does nothing.

113 | */ 114 | @Override public void enterAllocInst(ckaParser.AllocInstContext ctx) { } 115 | /** 116 | * {@inheritDoc} 117 | * 118 | *

The default implementation does nothing.

119 | */ 120 | @Override public void exitAllocInst(ckaParser.AllocInstContext ctx) { } 121 | /** 122 | * {@inheritDoc} 123 | * 124 | *

The default implementation does nothing.

125 | */ 126 | @Override public void enterNcallInst(ckaParser.NcallInstContext ctx) { } 127 | /** 128 | * {@inheritDoc} 129 | * 130 | *

The default implementation does nothing.

131 | */ 132 | @Override public void exitNcallInst(ckaParser.NcallInstContext ctx) { } 133 | /** 134 | * {@inheritDoc} 135 | * 136 | *

The default implementation does nothing.

137 | */ 138 | @Override public void enterLiteralLabelMnemonic(ckaParser.LiteralLabelMnemonicContext ctx) { } 139 | /** 140 | * {@inheritDoc} 141 | * 142 | *

The default implementation does nothing.

143 | */ 144 | @Override public void exitLiteralLabelMnemonic(ckaParser.LiteralLabelMnemonicContext ctx) { } 145 | /** 146 | * {@inheritDoc} 147 | * 148 | *

The default implementation does nothing.

149 | */ 150 | @Override public void enterLiteralIntMnemonic(ckaParser.LiteralIntMnemonicContext ctx) { } 151 | /** 152 | * {@inheritDoc} 153 | * 154 | *

The default implementation does nothing.

155 | */ 156 | @Override public void exitLiteralIntMnemonic(ckaParser.LiteralIntMnemonicContext ctx) { } 157 | /** 158 | * {@inheritDoc} 159 | * 160 | *

The default implementation does nothing.

161 | */ 162 | @Override public void enterLiteralStringMnemonic(ckaParser.LiteralStringMnemonicContext ctx) { } 163 | /** 164 | * {@inheritDoc} 165 | * 166 | *

The default implementation does nothing.

167 | */ 168 | @Override public void exitLiteralStringMnemonic(ckaParser.LiteralStringMnemonicContext ctx) { } 169 | /** 170 | * {@inheritDoc} 171 | * 172 | *

The default implementation does nothing.

173 | */ 174 | @Override public void enterSimpleInstruction(ckaParser.SimpleInstructionContext ctx) { } 175 | /** 176 | * {@inheritDoc} 177 | * 178 | *

The default implementation does nothing.

179 | */ 180 | @Override public void exitSimpleInstruction(ckaParser.SimpleInstructionContext ctx) { } 181 | /** 182 | * {@inheritDoc} 183 | * 184 | *

The default implementation does nothing.

185 | */ 186 | @Override public void enterEmptyFrameLayout(ckaParser.EmptyFrameLayoutContext ctx) { } 187 | /** 188 | * {@inheritDoc} 189 | * 190 | *

The default implementation does nothing.

191 | */ 192 | @Override public void exitEmptyFrameLayout(ckaParser.EmptyFrameLayoutContext ctx) { } 193 | /** 194 | * {@inheritDoc} 195 | * 196 | *

The default implementation does nothing.

197 | */ 198 | @Override public void enterNonEmptyFrameLayout(ckaParser.NonEmptyFrameLayoutContext ctx) { } 199 | /** 200 | * {@inheritDoc} 201 | * 202 | *

The default implementation does nothing.

203 | */ 204 | @Override public void exitNonEmptyFrameLayout(ckaParser.NonEmptyFrameLayoutContext ctx) { } 205 | /** 206 | * {@inheritDoc} 207 | * 208 | *

The default implementation does nothing.

209 | */ 210 | @Override public void enterRefArrayLayout(ckaParser.RefArrayLayoutContext ctx) { } 211 | /** 212 | * {@inheritDoc} 213 | * 214 | *

The default implementation does nothing.

215 | */ 216 | @Override public void exitRefArrayLayout(ckaParser.RefArrayLayoutContext ctx) { } 217 | /** 218 | * {@inheritDoc} 219 | * 220 | *

The default implementation does nothing.

221 | */ 222 | @Override public void enterEmptyCustomLayout(ckaParser.EmptyCustomLayoutContext ctx) { } 223 | /** 224 | * {@inheritDoc} 225 | * 226 | *

The default implementation does nothing.

227 | */ 228 | @Override public void exitEmptyCustomLayout(ckaParser.EmptyCustomLayoutContext ctx) { } 229 | /** 230 | * {@inheritDoc} 231 | * 232 | *

The default implementation does nothing.

233 | */ 234 | @Override public void enterCustomLayout(ckaParser.CustomLayoutContext ctx) { } 235 | /** 236 | * {@inheritDoc} 237 | * 238 | *

The default implementation does nothing.

239 | */ 240 | @Override public void exitCustomLayout(ckaParser.CustomLayoutContext ctx) { } 241 | /** 242 | * {@inheritDoc} 243 | * 244 | *

The default implementation does nothing.

245 | */ 246 | @Override public void enterInteger(ckaParser.IntegerContext ctx) { } 247 | /** 248 | * {@inheritDoc} 249 | * 250 | *

The default implementation does nothing.

251 | */ 252 | @Override public void exitInteger(ckaParser.IntegerContext ctx) { } 253 | 254 | /** 255 | * {@inheritDoc} 256 | * 257 | *

The default implementation does nothing.

258 | */ 259 | @Override public void enterEveryRule(ParserRuleContext ctx) { } 260 | /** 261 | * {@inheritDoc} 262 | * 263 | *

The default implementation does nothing.

264 | */ 265 | @Override public void exitEveryRule(ParserRuleContext ctx) { } 266 | /** 267 | * {@inheritDoc} 268 | * 269 | *

The default implementation does nothing.

270 | */ 271 | @Override public void visitTerminal(TerminalNode node) { } 272 | /** 273 | * {@inheritDoc} 274 | * 275 | *

The default implementation does nothing.

276 | */ 277 | @Override public void visitErrorNode(ErrorNode node) { } 278 | } -------------------------------------------------------------------------------- /compiler/cka/gen/ckaBaseVisitor.java: -------------------------------------------------------------------------------- 1 | // Generated from /Users/colinholzman/Documents/CopperKitten/compiler/cka/grammar/cka.g4 by ANTLR 4.7.2 2 | import org.antlr.v4.runtime.tree.AbstractParseTreeVisitor; 3 | 4 | /** 5 | * This class provides an empty implementation of {@link ckaVisitor}, 6 | * which can be extended to create a visitor which only needs to handle a subset 7 | * of the available methods. 8 | * 9 | * @param The return type of the visit operation. Use {@link Void} for 10 | * operations with no return type. 11 | */ 12 | public class ckaBaseVisitor extends AbstractParseTreeVisitor implements ckaVisitor { 13 | /** 14 | * {@inheritDoc} 15 | * 16 | *

The default implementation returns the result of calling 17 | * {@link #visitChildren} on {@code ctx}.

18 | */ 19 | @Override public T visitFile(ckaParser.FileContext ctx) { return visitChildren(ctx); } 20 | /** 21 | * {@inheritDoc} 22 | * 23 | *

The default implementation returns the result of calling 24 | * {@link #visitChildren} on {@code ctx}.

25 | */ 26 | @Override public T visitInstructions(ckaParser.InstructionsContext ctx) { return visitChildren(ctx); } 27 | /** 28 | * {@inheritDoc} 29 | * 30 | *

The default implementation returns the result of calling 31 | * {@link #visitChildren} on {@code ctx}.

32 | */ 33 | @Override public T visitLabelInst(ckaParser.LabelInstContext ctx) { return visitChildren(ctx); } 34 | /** 35 | * {@inheritDoc} 36 | * 37 | *

The default implementation returns the result of calling 38 | * {@link #visitChildren} on {@code ctx}.

39 | */ 40 | @Override public T visitSimpleInst(ckaParser.SimpleInstContext ctx) { return visitChildren(ctx); } 41 | /** 42 | * {@inheritDoc} 43 | * 44 | *

The default implementation returns the result of calling 45 | * {@link #visitChildren} on {@code ctx}.

46 | */ 47 | @Override public T visitLiteralIntInst(ckaParser.LiteralIntInstContext ctx) { return visitChildren(ctx); } 48 | /** 49 | * {@inheritDoc} 50 | * 51 | *

The default implementation returns the result of calling 52 | * {@link #visitChildren} on {@code ctx}.

53 | */ 54 | @Override public T visitLiteralLabelInst(ckaParser.LiteralLabelInstContext ctx) { return visitChildren(ctx); } 55 | /** 56 | * {@inheritDoc} 57 | * 58 | *

The default implementation returns the result of calling 59 | * {@link #visitChildren} on {@code ctx}.

60 | */ 61 | @Override public T visitLiteralStringInst(ckaParser.LiteralStringInstContext ctx) { return visitChildren(ctx); } 62 | /** 63 | * {@inheritDoc} 64 | * 65 | *

The default implementation returns the result of calling 66 | * {@link #visitChildren} on {@code ctx}.

67 | */ 68 | @Override public T visitLayoutInst(ckaParser.LayoutInstContext ctx) { return visitChildren(ctx); } 69 | /** 70 | * {@inheritDoc} 71 | * 72 | *

The default implementation returns the result of calling 73 | * {@link #visitChildren} on {@code ctx}.

74 | */ 75 | @Override public T visitAllocInst(ckaParser.AllocInstContext ctx) { return visitChildren(ctx); } 76 | /** 77 | * {@inheritDoc} 78 | * 79 | *

The default implementation returns the result of calling 80 | * {@link #visitChildren} on {@code ctx}.

81 | */ 82 | @Override public T visitNcallInst(ckaParser.NcallInstContext ctx) { return visitChildren(ctx); } 83 | /** 84 | * {@inheritDoc} 85 | * 86 | *

The default implementation returns the result of calling 87 | * {@link #visitChildren} on {@code ctx}.

88 | */ 89 | @Override public T visitLiteralLabelMnemonic(ckaParser.LiteralLabelMnemonicContext ctx) { return visitChildren(ctx); } 90 | /** 91 | * {@inheritDoc} 92 | * 93 | *

The default implementation returns the result of calling 94 | * {@link #visitChildren} on {@code ctx}.

95 | */ 96 | @Override public T visitLiteralIntMnemonic(ckaParser.LiteralIntMnemonicContext ctx) { return visitChildren(ctx); } 97 | /** 98 | * {@inheritDoc} 99 | * 100 | *

The default implementation returns the result of calling 101 | * {@link #visitChildren} on {@code ctx}.

102 | */ 103 | @Override public T visitLiteralStringMnemonic(ckaParser.LiteralStringMnemonicContext ctx) { return visitChildren(ctx); } 104 | /** 105 | * {@inheritDoc} 106 | * 107 | *

The default implementation returns the result of calling 108 | * {@link #visitChildren} on {@code ctx}.

109 | */ 110 | @Override public T visitSimpleInstruction(ckaParser.SimpleInstructionContext ctx) { return visitChildren(ctx); } 111 | /** 112 | * {@inheritDoc} 113 | * 114 | *

The default implementation returns the result of calling 115 | * {@link #visitChildren} on {@code ctx}.

116 | */ 117 | @Override public T visitEmptyFrameLayout(ckaParser.EmptyFrameLayoutContext ctx) { return visitChildren(ctx); } 118 | /** 119 | * {@inheritDoc} 120 | * 121 | *

The default implementation returns the result of calling 122 | * {@link #visitChildren} on {@code ctx}.

123 | */ 124 | @Override public T visitNonEmptyFrameLayout(ckaParser.NonEmptyFrameLayoutContext ctx) { return visitChildren(ctx); } 125 | /** 126 | * {@inheritDoc} 127 | * 128 | *

The default implementation returns the result of calling 129 | * {@link #visitChildren} on {@code ctx}.

130 | */ 131 | @Override public T visitRefArrayLayout(ckaParser.RefArrayLayoutContext ctx) { return visitChildren(ctx); } 132 | /** 133 | * {@inheritDoc} 134 | * 135 | *

The default implementation returns the result of calling 136 | * {@link #visitChildren} on {@code ctx}.

137 | */ 138 | @Override public T visitEmptyCustomLayout(ckaParser.EmptyCustomLayoutContext ctx) { return visitChildren(ctx); } 139 | /** 140 | * {@inheritDoc} 141 | * 142 | *

The default implementation returns the result of calling 143 | * {@link #visitChildren} on {@code ctx}.

144 | */ 145 | @Override public T visitCustomLayout(ckaParser.CustomLayoutContext ctx) { return visitChildren(ctx); } 146 | /** 147 | * {@inheritDoc} 148 | * 149 | *

The default implementation returns the result of calling 150 | * {@link #visitChildren} on {@code ctx}.

151 | */ 152 | @Override public T visitInteger(ckaParser.IntegerContext ctx) { return visitChildren(ctx); } 153 | } -------------------------------------------------------------------------------- /compiler/cka/gen/ckaLexer.tokens: -------------------------------------------------------------------------------- 1 | T__0=1 2 | T__1=2 3 | T__2=3 4 | T__3=4 5 | T__4=5 6 | T__5=6 7 | T__6=7 8 | T__7=8 9 | T__8=9 10 | T__9=10 11 | T__10=11 12 | T__11=12 13 | T__12=13 14 | T__13=14 15 | T__14=15 16 | T__15=16 17 | T__16=17 18 | T__17=18 19 | T__18=19 20 | T__19=20 21 | T__20=21 22 | T__21=22 23 | T__22=23 24 | T__23=24 25 | T__24=25 26 | T__25=26 27 | T__26=27 28 | T__27=28 29 | T__28=29 30 | T__29=30 31 | T__30=31 32 | T__31=32 33 | T__32=33 34 | T__33=34 35 | T__34=35 36 | T__35=36 37 | T__36=37 38 | T__37=38 39 | T__38=39 40 | T__39=40 41 | T__40=41 42 | T__41=42 43 | T__42=43 44 | T__43=44 45 | T__44=45 46 | T__45=46 47 | T__46=47 48 | T__47=48 49 | T__48=49 50 | T__49=50 51 | T__50=51 52 | T__51=52 53 | T__52=53 54 | T__53=54 55 | T__54=55 56 | T__55=56 57 | T__56=57 58 | T__57=58 59 | NATURAL=59 60 | ID=60 61 | LABEL=61 62 | STRING=62 63 | WHITESPACE=63 64 | COMMENT=64 65 | ':'=1 66 | 'layout'=2 67 | 'alloc'=3 68 | 'ncall'=4 69 | 'push'=5 70 | 'jump'=6 71 | 'jumpz'=7 72 | 'jumpnz'=8 73 | 'aload'=9 74 | 'astore'=10 75 | 'lload'=11 76 | 'lstore'=12 77 | 'rload'=13 78 | 'rstore'=14 79 | 'cload'=15 80 | 'cstore'=16 81 | 'debugpush'=17 82 | 'add'=18 83 | 'sub'=19 84 | 'mul'=20 85 | 'div'=21 86 | 'mod'=22 87 | 'shl'=23 88 | 'shr'=24 89 | 'neg'=25 90 | 'not'=26 91 | 'bitnot'=27 92 | 'bitand'=28 93 | 'bitxor'=29 94 | 'bitor'=30 95 | 'lt'=31 96 | 'lte'=32 97 | 'gt'=33 98 | 'gte'=34 99 | 'eq'=35 100 | 'neq'=36 101 | 'cmp'=37 102 | 'call'=38 103 | 'return'=39 104 | 'dup'=40 105 | 'pop'=41 106 | 'swap'=42 107 | 'enter'=43 108 | 'leave'=44 109 | 'nop'=45 110 | 'halt'=46 111 | 'load'=47 112 | 'store'=48 113 | 'rbarrier'=49 114 | 'wbarrier'=50 115 | 'debugpop'=51 116 | 'clear'=52 117 | 'goto'=53 118 | '['=54 119 | ']'=55 120 | ','=56 121 | '*'=57 122 | '-'=58 123 | -------------------------------------------------------------------------------- /compiler/cka/gen/ckaListener.java: -------------------------------------------------------------------------------- 1 | // Generated from /Users/colinholzman/Documents/CopperKitten/compiler/cka/grammar/cka.g4 by ANTLR 4.7.2 2 | import org.antlr.v4.runtime.tree.ParseTreeListener; 3 | 4 | /** 5 | * This interface defines a complete listener for a parse tree produced by 6 | * {@link ckaParser}. 7 | */ 8 | public interface ckaListener extends ParseTreeListener { 9 | /** 10 | * Enter a parse tree produced by {@link ckaParser#file}. 11 | * @param ctx the parse tree 12 | */ 13 | void enterFile(ckaParser.FileContext ctx); 14 | /** 15 | * Exit a parse tree produced by {@link ckaParser#file}. 16 | * @param ctx the parse tree 17 | */ 18 | void exitFile(ckaParser.FileContext ctx); 19 | /** 20 | * Enter a parse tree produced by {@link ckaParser#instructions}. 21 | * @param ctx the parse tree 22 | */ 23 | void enterInstructions(ckaParser.InstructionsContext ctx); 24 | /** 25 | * Exit a parse tree produced by {@link ckaParser#instructions}. 26 | * @param ctx the parse tree 27 | */ 28 | void exitInstructions(ckaParser.InstructionsContext ctx); 29 | /** 30 | * Enter a parse tree produced by the {@code labelInst} 31 | * labeled alternative in {@link ckaParser#instruction}. 32 | * @param ctx the parse tree 33 | */ 34 | void enterLabelInst(ckaParser.LabelInstContext ctx); 35 | /** 36 | * Exit a parse tree produced by the {@code labelInst} 37 | * labeled alternative in {@link ckaParser#instruction}. 38 | * @param ctx the parse tree 39 | */ 40 | void exitLabelInst(ckaParser.LabelInstContext ctx); 41 | /** 42 | * Enter a parse tree produced by the {@code simpleInst} 43 | * labeled alternative in {@link ckaParser#instruction}. 44 | * @param ctx the parse tree 45 | */ 46 | void enterSimpleInst(ckaParser.SimpleInstContext ctx); 47 | /** 48 | * Exit a parse tree produced by the {@code simpleInst} 49 | * labeled alternative in {@link ckaParser#instruction}. 50 | * @param ctx the parse tree 51 | */ 52 | void exitSimpleInst(ckaParser.SimpleInstContext ctx); 53 | /** 54 | * Enter a parse tree produced by the {@code literalIntInst} 55 | * labeled alternative in {@link ckaParser#instruction}. 56 | * @param ctx the parse tree 57 | */ 58 | void enterLiteralIntInst(ckaParser.LiteralIntInstContext ctx); 59 | /** 60 | * Exit a parse tree produced by the {@code literalIntInst} 61 | * labeled alternative in {@link ckaParser#instruction}. 62 | * @param ctx the parse tree 63 | */ 64 | void exitLiteralIntInst(ckaParser.LiteralIntInstContext ctx); 65 | /** 66 | * Enter a parse tree produced by the {@code literalLabelInst} 67 | * labeled alternative in {@link ckaParser#instruction}. 68 | * @param ctx the parse tree 69 | */ 70 | void enterLiteralLabelInst(ckaParser.LiteralLabelInstContext ctx); 71 | /** 72 | * Exit a parse tree produced by the {@code literalLabelInst} 73 | * labeled alternative in {@link ckaParser#instruction}. 74 | * @param ctx the parse tree 75 | */ 76 | void exitLiteralLabelInst(ckaParser.LiteralLabelInstContext ctx); 77 | /** 78 | * Enter a parse tree produced by the {@code literalStringInst} 79 | * labeled alternative in {@link ckaParser#instruction}. 80 | * @param ctx the parse tree 81 | */ 82 | void enterLiteralStringInst(ckaParser.LiteralStringInstContext ctx); 83 | /** 84 | * Exit a parse tree produced by the {@code literalStringInst} 85 | * labeled alternative in {@link ckaParser#instruction}. 86 | * @param ctx the parse tree 87 | */ 88 | void exitLiteralStringInst(ckaParser.LiteralStringInstContext ctx); 89 | /** 90 | * Enter a parse tree produced by the {@code layoutInst} 91 | * labeled alternative in {@link ckaParser#instruction}. 92 | * @param ctx the parse tree 93 | */ 94 | void enterLayoutInst(ckaParser.LayoutInstContext ctx); 95 | /** 96 | * Exit a parse tree produced by the {@code layoutInst} 97 | * labeled alternative in {@link ckaParser#instruction}. 98 | * @param ctx the parse tree 99 | */ 100 | void exitLayoutInst(ckaParser.LayoutInstContext ctx); 101 | /** 102 | * Enter a parse tree produced by the {@code allocInst} 103 | * labeled alternative in {@link ckaParser#instruction}. 104 | * @param ctx the parse tree 105 | */ 106 | void enterAllocInst(ckaParser.AllocInstContext ctx); 107 | /** 108 | * Exit a parse tree produced by the {@code allocInst} 109 | * labeled alternative in {@link ckaParser#instruction}. 110 | * @param ctx the parse tree 111 | */ 112 | void exitAllocInst(ckaParser.AllocInstContext ctx); 113 | /** 114 | * Enter a parse tree produced by the {@code ncallInst} 115 | * labeled alternative in {@link ckaParser#instruction}. 116 | * @param ctx the parse tree 117 | */ 118 | void enterNcallInst(ckaParser.NcallInstContext ctx); 119 | /** 120 | * Exit a parse tree produced by the {@code ncallInst} 121 | * labeled alternative in {@link ckaParser#instruction}. 122 | * @param ctx the parse tree 123 | */ 124 | void exitNcallInst(ckaParser.NcallInstContext ctx); 125 | /** 126 | * Enter a parse tree produced by {@link ckaParser#literalLabelMnemonic}. 127 | * @param ctx the parse tree 128 | */ 129 | void enterLiteralLabelMnemonic(ckaParser.LiteralLabelMnemonicContext ctx); 130 | /** 131 | * Exit a parse tree produced by {@link ckaParser#literalLabelMnemonic}. 132 | * @param ctx the parse tree 133 | */ 134 | void exitLiteralLabelMnemonic(ckaParser.LiteralLabelMnemonicContext ctx); 135 | /** 136 | * Enter a parse tree produced by {@link ckaParser#literalIntMnemonic}. 137 | * @param ctx the parse tree 138 | */ 139 | void enterLiteralIntMnemonic(ckaParser.LiteralIntMnemonicContext ctx); 140 | /** 141 | * Exit a parse tree produced by {@link ckaParser#literalIntMnemonic}. 142 | * @param ctx the parse tree 143 | */ 144 | void exitLiteralIntMnemonic(ckaParser.LiteralIntMnemonicContext ctx); 145 | /** 146 | * Enter a parse tree produced by {@link ckaParser#literalStringMnemonic}. 147 | * @param ctx the parse tree 148 | */ 149 | void enterLiteralStringMnemonic(ckaParser.LiteralStringMnemonicContext ctx); 150 | /** 151 | * Exit a parse tree produced by {@link ckaParser#literalStringMnemonic}. 152 | * @param ctx the parse tree 153 | */ 154 | void exitLiteralStringMnemonic(ckaParser.LiteralStringMnemonicContext ctx); 155 | /** 156 | * Enter a parse tree produced by {@link ckaParser#simpleInstruction}. 157 | * @param ctx the parse tree 158 | */ 159 | void enterSimpleInstruction(ckaParser.SimpleInstructionContext ctx); 160 | /** 161 | * Exit a parse tree produced by {@link ckaParser#simpleInstruction}. 162 | * @param ctx the parse tree 163 | */ 164 | void exitSimpleInstruction(ckaParser.SimpleInstructionContext ctx); 165 | /** 166 | * Enter a parse tree produced by the {@code emptyFrameLayout} 167 | * labeled alternative in {@link ckaParser#frameLayout}. 168 | * @param ctx the parse tree 169 | */ 170 | void enterEmptyFrameLayout(ckaParser.EmptyFrameLayoutContext ctx); 171 | /** 172 | * Exit a parse tree produced by the {@code emptyFrameLayout} 173 | * labeled alternative in {@link ckaParser#frameLayout}. 174 | * @param ctx the parse tree 175 | */ 176 | void exitEmptyFrameLayout(ckaParser.EmptyFrameLayoutContext ctx); 177 | /** 178 | * Enter a parse tree produced by the {@code nonEmptyFrameLayout} 179 | * labeled alternative in {@link ckaParser#frameLayout}. 180 | * @param ctx the parse tree 181 | */ 182 | void enterNonEmptyFrameLayout(ckaParser.NonEmptyFrameLayoutContext ctx); 183 | /** 184 | * Exit a parse tree produced by the {@code nonEmptyFrameLayout} 185 | * labeled alternative in {@link ckaParser#frameLayout}. 186 | * @param ctx the parse tree 187 | */ 188 | void exitNonEmptyFrameLayout(ckaParser.NonEmptyFrameLayoutContext ctx); 189 | /** 190 | * Enter a parse tree produced by the {@code refArrayLayout} 191 | * labeled alternative in {@link ckaParser#allocLayout}. 192 | * @param ctx the parse tree 193 | */ 194 | void enterRefArrayLayout(ckaParser.RefArrayLayoutContext ctx); 195 | /** 196 | * Exit a parse tree produced by the {@code refArrayLayout} 197 | * labeled alternative in {@link ckaParser#allocLayout}. 198 | * @param ctx the parse tree 199 | */ 200 | void exitRefArrayLayout(ckaParser.RefArrayLayoutContext ctx); 201 | /** 202 | * Enter a parse tree produced by the {@code emptyCustomLayout} 203 | * labeled alternative in {@link ckaParser#allocLayout}. 204 | * @param ctx the parse tree 205 | */ 206 | void enterEmptyCustomLayout(ckaParser.EmptyCustomLayoutContext ctx); 207 | /** 208 | * Exit a parse tree produced by the {@code emptyCustomLayout} 209 | * labeled alternative in {@link ckaParser#allocLayout}. 210 | * @param ctx the parse tree 211 | */ 212 | void exitEmptyCustomLayout(ckaParser.EmptyCustomLayoutContext ctx); 213 | /** 214 | * Enter a parse tree produced by the {@code customLayout} 215 | * labeled alternative in {@link ckaParser#allocLayout}. 216 | * @param ctx the parse tree 217 | */ 218 | void enterCustomLayout(ckaParser.CustomLayoutContext ctx); 219 | /** 220 | * Exit a parse tree produced by the {@code customLayout} 221 | * labeled alternative in {@link ckaParser#allocLayout}. 222 | * @param ctx the parse tree 223 | */ 224 | void exitCustomLayout(ckaParser.CustomLayoutContext ctx); 225 | /** 226 | * Enter a parse tree produced by {@link ckaParser#integer}. 227 | * @param ctx the parse tree 228 | */ 229 | void enterInteger(ckaParser.IntegerContext ctx); 230 | /** 231 | * Exit a parse tree produced by {@link ckaParser#integer}. 232 | * @param ctx the parse tree 233 | */ 234 | void exitInteger(ckaParser.IntegerContext ctx); 235 | } -------------------------------------------------------------------------------- /compiler/cka/gen/ckaVisitor.java: -------------------------------------------------------------------------------- 1 | // Generated from /Users/colinholzman/Documents/CopperKitten/compiler/cka/grammar/cka.g4 by ANTLR 4.7.2 2 | import org.antlr.v4.runtime.tree.ParseTreeVisitor; 3 | 4 | /** 5 | * This interface defines a complete generic visitor for a parse tree produced 6 | * by {@link ckaParser}. 7 | * 8 | * @param The return type of the visit operation. Use {@link Void} for 9 | * operations with no return type. 10 | */ 11 | public interface ckaVisitor extends ParseTreeVisitor { 12 | /** 13 | * Visit a parse tree produced by {@link ckaParser#file}. 14 | * @param ctx the parse tree 15 | * @return the visitor result 16 | */ 17 | T visitFile(ckaParser.FileContext ctx); 18 | /** 19 | * Visit a parse tree produced by {@link ckaParser#instructions}. 20 | * @param ctx the parse tree 21 | * @return the visitor result 22 | */ 23 | T visitInstructions(ckaParser.InstructionsContext ctx); 24 | /** 25 | * Visit a parse tree produced by the {@code labelInst} 26 | * labeled alternative in {@link ckaParser#instruction}. 27 | * @param ctx the parse tree 28 | * @return the visitor result 29 | */ 30 | T visitLabelInst(ckaParser.LabelInstContext ctx); 31 | /** 32 | * Visit a parse tree produced by the {@code simpleInst} 33 | * labeled alternative in {@link ckaParser#instruction}. 34 | * @param ctx the parse tree 35 | * @return the visitor result 36 | */ 37 | T visitSimpleInst(ckaParser.SimpleInstContext ctx); 38 | /** 39 | * Visit a parse tree produced by the {@code literalIntInst} 40 | * labeled alternative in {@link ckaParser#instruction}. 41 | * @param ctx the parse tree 42 | * @return the visitor result 43 | */ 44 | T visitLiteralIntInst(ckaParser.LiteralIntInstContext ctx); 45 | /** 46 | * Visit a parse tree produced by the {@code literalLabelInst} 47 | * labeled alternative in {@link ckaParser#instruction}. 48 | * @param ctx the parse tree 49 | * @return the visitor result 50 | */ 51 | T visitLiteralLabelInst(ckaParser.LiteralLabelInstContext ctx); 52 | /** 53 | * Visit a parse tree produced by the {@code literalStringInst} 54 | * labeled alternative in {@link ckaParser#instruction}. 55 | * @param ctx the parse tree 56 | * @return the visitor result 57 | */ 58 | T visitLiteralStringInst(ckaParser.LiteralStringInstContext ctx); 59 | /** 60 | * Visit a parse tree produced by the {@code layoutInst} 61 | * labeled alternative in {@link ckaParser#instruction}. 62 | * @param ctx the parse tree 63 | * @return the visitor result 64 | */ 65 | T visitLayoutInst(ckaParser.LayoutInstContext ctx); 66 | /** 67 | * Visit a parse tree produced by the {@code allocInst} 68 | * labeled alternative in {@link ckaParser#instruction}. 69 | * @param ctx the parse tree 70 | * @return the visitor result 71 | */ 72 | T visitAllocInst(ckaParser.AllocInstContext ctx); 73 | /** 74 | * Visit a parse tree produced by the {@code ncallInst} 75 | * labeled alternative in {@link ckaParser#instruction}. 76 | * @param ctx the parse tree 77 | * @return the visitor result 78 | */ 79 | T visitNcallInst(ckaParser.NcallInstContext ctx); 80 | /** 81 | * Visit a parse tree produced by {@link ckaParser#literalLabelMnemonic}. 82 | * @param ctx the parse tree 83 | * @return the visitor result 84 | */ 85 | T visitLiteralLabelMnemonic(ckaParser.LiteralLabelMnemonicContext ctx); 86 | /** 87 | * Visit a parse tree produced by {@link ckaParser#literalIntMnemonic}. 88 | * @param ctx the parse tree 89 | * @return the visitor result 90 | */ 91 | T visitLiteralIntMnemonic(ckaParser.LiteralIntMnemonicContext ctx); 92 | /** 93 | * Visit a parse tree produced by {@link ckaParser#literalStringMnemonic}. 94 | * @param ctx the parse tree 95 | * @return the visitor result 96 | */ 97 | T visitLiteralStringMnemonic(ckaParser.LiteralStringMnemonicContext ctx); 98 | /** 99 | * Visit a parse tree produced by {@link ckaParser#simpleInstruction}. 100 | * @param ctx the parse tree 101 | * @return the visitor result 102 | */ 103 | T visitSimpleInstruction(ckaParser.SimpleInstructionContext ctx); 104 | /** 105 | * Visit a parse tree produced by the {@code emptyFrameLayout} 106 | * labeled alternative in {@link ckaParser#frameLayout}. 107 | * @param ctx the parse tree 108 | * @return the visitor result 109 | */ 110 | T visitEmptyFrameLayout(ckaParser.EmptyFrameLayoutContext ctx); 111 | /** 112 | * Visit a parse tree produced by the {@code nonEmptyFrameLayout} 113 | * labeled alternative in {@link ckaParser#frameLayout}. 114 | * @param ctx the parse tree 115 | * @return the visitor result 116 | */ 117 | T visitNonEmptyFrameLayout(ckaParser.NonEmptyFrameLayoutContext ctx); 118 | /** 119 | * Visit a parse tree produced by the {@code refArrayLayout} 120 | * labeled alternative in {@link ckaParser#allocLayout}. 121 | * @param ctx the parse tree 122 | * @return the visitor result 123 | */ 124 | T visitRefArrayLayout(ckaParser.RefArrayLayoutContext ctx); 125 | /** 126 | * Visit a parse tree produced by the {@code emptyCustomLayout} 127 | * labeled alternative in {@link ckaParser#allocLayout}. 128 | * @param ctx the parse tree 129 | * @return the visitor result 130 | */ 131 | T visitEmptyCustomLayout(ckaParser.EmptyCustomLayoutContext ctx); 132 | /** 133 | * Visit a parse tree produced by the {@code customLayout} 134 | * labeled alternative in {@link ckaParser#allocLayout}. 135 | * @param ctx the parse tree 136 | * @return the visitor result 137 | */ 138 | T visitCustomLayout(ckaParser.CustomLayoutContext ctx); 139 | /** 140 | * Visit a parse tree produced by {@link ckaParser#integer}. 141 | * @param ctx the parse tree 142 | * @return the visitor result 143 | */ 144 | T visitInteger(ckaParser.IntegerContext ctx); 145 | } -------------------------------------------------------------------------------- /compiler/cka/grammar/cka.g4: -------------------------------------------------------------------------------- 1 | 2 | 3 | grammar cka; 4 | 5 | //basic CK 6 | 7 | file 8 | : instructions? EOF 9 | ; 10 | 11 | instructions 12 | : instruction ( instruction )* 13 | ; 14 | 15 | instruction 16 | : LABEL ':' #labelInst 17 | | simpleInstruction #simpleInst 18 | | literalIntMnemonic integer #literalIntInst 19 | | literalLabelMnemonic LABEL #literalLabelInst 20 | | literalStringMnemonic STRING #literalStringInst 21 | | 'layout' frameLayout #layoutInst 22 | | 'alloc' allocLayout #allocInst 23 | | 'ncall' ID #ncallInst 24 | ; 25 | 26 | literalLabelMnemonic 27 | : 'push' 28 | | 'jump' 29 | | 'jumpz' 30 | | 'jumpnz' 31 | ; 32 | 33 | literalIntMnemonic 34 | : 'push' 35 | | 'aload' 36 | | 'astore' 37 | | 'lload' 38 | | 'lstore' 39 | | 'rload' 40 | | 'rstore' 41 | | 'cload' 42 | | 'cstore' 43 | ; 44 | 45 | literalStringMnemonic 46 | : 'debugpush' 47 | ; 48 | 49 | simpleInstruction 50 | : 'add' 51 | | 'sub' 52 | | 'mul' 53 | | 'div' 54 | | 'mod' 55 | | 'shl' 56 | | 'shr' 57 | | 'neg' 58 | | 'not' 59 | | 'bitnot' 60 | | 'bitand' 61 | | 'bitxor' 62 | | 'bitor' 63 | | 'lt' 64 | | 'lte' 65 | | 'gt' 66 | | 'gte' 67 | | 'eq' 68 | | 'neq' 69 | | 'cmp' 70 | | 'call' 71 | | 'return' 72 | | 'dup' 73 | | 'pop' 74 | | 'swap' 75 | | 'enter' 76 | | 'leave' 77 | | 'nop' 78 | | 'halt' 79 | | 'load' 80 | | 'store' 81 | | 'rbarrier' 82 | | 'wbarrier' 83 | | 'debugpop' 84 | | 'clear' 85 | | 'goto' 86 | ; 87 | 88 | frameLayout 89 | : '[' ']' #emptyFrameLayout 90 | | '[' NATURAL ( ',' NATURAL )* ']' #nonEmptyFrameLayout 91 | ; 92 | 93 | allocLayout 94 | : '[' '*' ']' #refArrayLayout 95 | | '[' ']' #emptyCustomLayout 96 | | '[' NATURAL ( ',' NATURAL )* ']' #customLayout 97 | ; 98 | 99 | integer : '-'? NATURAL ; 100 | 101 | NATURAL : ('0'..'9')+ ; 102 | 103 | ID : ('_'|'a'..'z') ('_'|'0'..'9'|'a'..'z'|'A'..'Z')* ; 104 | LABEL : ('A'..'Z') ('_'|'0'..'9'|'a'..'z'|'A'..'Z')* ; 105 | 106 | STRING 107 | : '"' ('\\' ('\\'|'\t'|'\r\n'|'\r'|'\n'|'"') | ~('\\'|'\t'|'\r'|'\n'|'"') )* '"' 108 | ; 109 | 110 | //NL : '\n'|'\r\n' ; 111 | 112 | WHITESPACE : (' '|'\t'|'\u000C'|'\n'|'\r\n') -> skip ; 113 | COMMENT : '//' ~('\n'|'\r')* '\r'? '\n' -> skip ; 114 | -------------------------------------------------------------------------------- /compiler/cka/src/Cli.kt: -------------------------------------------------------------------------------- 1 | import org.antlr.v4.runtime.CharStreams 2 | import org.antlr.v4.runtime.CommonTokenStream 3 | import org.apache.commons.cli.*; 4 | import util.antlr.ThrowingErrorListener 5 | import java.io.File 6 | 7 | class Cli(val args: Array) { 8 | 9 | private val options = Options() 10 | 11 | init { 12 | options.addOption("h", "help", false, "show help") 13 | options.addRequiredOption("i", "input", true, "input file") 14 | options.addOption("o", "output", true, "output file") 15 | options.addOption("s", "stack_size", true, "set stack size (in words)") 16 | options.addOption("m", "memory_size", true, "set heap size (in words)") 17 | options.addOption("w", "word_size", true, "set heap size (in bytes)") 18 | options.addOption("g", "garbage_collector", true, "set garbage collector implementation (copying, incremental, mark_compact)") 19 | } 20 | 21 | fun parse() { 22 | 23 | val parser = DefaultParser() 24 | 25 | val cmd: CommandLine? 26 | try { 27 | cmd = parser.parse(options, args) 28 | 29 | if (cmd!!.hasOption("h")) { 30 | help() 31 | } else { 32 | 33 | val inputFileName = cmd.getOptionValue("i")!! 34 | val outputFileName = cmd.getOptionValue("o") 35 | val stackSize = cmd.getOptionValue("s") 36 | val heapSize = cmd.getOptionValue("m") 37 | val wordSize = cmd.getOptionValue("w") 38 | var gcOpt = cmd.getOptionValue("g") 39 | 40 | val gcOpts = listOf("copying", "incremental", "mark_compact") 41 | 42 | if (gcOpt != null) { 43 | if (!gcOpts.contains(gcOpt.toLowerCase())) { 44 | println("unknown option $gcOpt") 45 | help() 46 | return 47 | } 48 | } else { 49 | gcOpt = "copying" 50 | } 51 | 52 | val gcImpls = gcOpts.map { o -> Pair(o, "${o}_gc.h") }.toMap() 53 | val gcImpl = gcImpls.getValue(gcOpt.toLowerCase()) 54 | 55 | val oc = OutputContext( 56 | { mnemonic -> mnemonic.toUpperCase() }, 57 | wordSize?.toInt() ?: 4, 58 | heapSize?.toInt() ?: 1000, 59 | stackSize?.toInt() ?: 100, 60 | gcImpl, 61 | ArrayList() 62 | ) 63 | 64 | val stream = CharStreams.fromFileName(inputFileName) 65 | val lexer = ckaLexer(stream) 66 | val tokens = CommonTokenStream(lexer) 67 | val ckaParser = ckaParser(tokens) 68 | ckaParser.removeErrorListeners() 69 | ckaParser.addErrorListener(ThrowingErrorListener()) 70 | val context = ckaParser.file() 71 | val pc = FileVisitor().visit(context) 72 | for (inst in pc.instructions) { 73 | inst.emit(pc, oc) 74 | } 75 | if (outputFileName != null) { 76 | File(outputFileName).printWriter().use { out -> 77 | out.print(oc.emit()) 78 | } 79 | } else { 80 | println(oc.emit()) 81 | } 82 | } 83 | 84 | } catch (e: ParseException) { 85 | help() 86 | } catch (e: RuntimeException) { 87 | e.printStackTrace() 88 | } 89 | 90 | } 91 | 92 | private fun help() { 93 | // This prints out some help 94 | HelpFormatter().printHelp("h", options) 95 | } 96 | } 97 | 98 | -------------------------------------------------------------------------------- /compiler/cka/src/FileVisitor.kt: -------------------------------------------------------------------------------- 1 | class FileVisitor : ckaBaseVisitor() { 2 | 3 | override fun visitFile(ctx: ckaParser.FileContext?): ParseContext { 4 | return InstructionsVisitor().visit(ctx!!.instructions()) 5 | } 6 | 7 | } 8 | 9 | class InstructionsVisitor : ckaBaseVisitor() { 10 | override fun visitInstructions(ctx: ckaParser.InstructionsContext?): ParseContext { 11 | val pc = ParseContext() 12 | for (inst in ctx!!.instruction()) { 13 | InstructionVisitor(pc).visit(inst) 14 | } 15 | return pc 16 | } 17 | } 18 | 19 | class InstructionVisitor(val pc: ParseContext) : ckaBaseVisitor() { 20 | 21 | override fun visitLabelInst(ctx: ckaParser.LabelInstContext?) { 22 | pc.labels[ctx!!.LABEL().text] = pc.instructions.count() 23 | } 24 | 25 | override fun visitSimpleInst(ctx: ckaParser.SimpleInstContext?) { 26 | pc.instructions.add(SimpleInstruction(ctx!!.simpleInstruction().text)) 27 | } 28 | 29 | override fun visitLiteralIntInst(ctx: ckaParser.LiteralIntInstContext?) { 30 | pc.instructions.add(LiteralIntInstruction(ctx!!.literalIntMnemonic().text, ctx.integer().text.toLong())) 31 | } 32 | 33 | override fun visitLiteralStringInst(ctx: ckaParser.LiteralStringInstContext?) { 34 | pc.instructions.add(LiteralStringInstruction(ctx!!.literalStringMnemonic().text, ctx.STRING().text.trim{c -> c == '"'})) 35 | } 36 | 37 | override fun visitLiteralLabelInst(ctx: ckaParser.LiteralLabelInstContext?) { 38 | pc.instructions.add(LiteralLabelInstruction(ctx!!.literalLabelMnemonic().text, ctx.LABEL().text)) 39 | } 40 | 41 | override fun visitLayoutInst(ctx: ckaParser.LayoutInstContext?) { 42 | pc.instructions.add(LayoutInstruction("layout", FrameLayoutVisitor().visit(ctx!!.frameLayout()))) 43 | } 44 | 45 | override fun visitAllocInst(ctx: ckaParser.AllocInstContext?) { 46 | pc.instructions.add(LayoutInstruction("alloc", AllocLayoutVisitor().visit(ctx!!.allocLayout()))) 47 | } 48 | 49 | override fun visitNcallInst(ctx: ckaParser.NcallInstContext?) { 50 | pc.instructions.add(NCallInstruction(ctx!!.ID().text)) 51 | } 52 | 53 | } 54 | 55 | open class FrameLayoutVisitor : ckaBaseVisitor() { 56 | override fun visitEmptyFrameLayout(ctx: ckaParser.EmptyFrameLayoutContext?): Function { 57 | return CustomLayoutFunction(ArrayList()) 58 | } 59 | 60 | override fun visitNonEmptyFrameLayout(ctx: ckaParser.NonEmptyFrameLayoutContext?): Function { 61 | return CustomLayoutFunction(ctx!!.NATURAL().map { node -> node.text.toInt() }) 62 | } 63 | } 64 | 65 | class AllocLayoutVisitor : FrameLayoutVisitor() { 66 | override fun visitRefArrayLayout(ctx: ckaParser.RefArrayLayoutContext?): Function { 67 | return RefArrayLayoutFunction 68 | } 69 | 70 | override fun visitEmptyCustomLayout(ctx: ckaParser.EmptyCustomLayoutContext?): Function { 71 | return CustomLayoutFunction(ArrayList()) 72 | } 73 | 74 | override fun visitCustomLayout(ctx: ckaParser.CustomLayoutContext?): Function { 75 | return CustomLayoutFunction(ctx!!.NATURAL().map { n -> n.text.toInt() }) 76 | } 77 | } -------------------------------------------------------------------------------- /compiler/cka/src/Function.kt: -------------------------------------------------------------------------------- 1 | //LayoutFunction represents a generated function that the ck garbage collector 2 | //will use to find object references util.either in the runtime stack or in gc managed objects 3 | //on the heap. 4 | //A layout function could be a custom layout where specific objects are marked as references 5 | //or it could be a ref array layout where all indices are refs and the number of such indices 6 | //is only known at runtime 7 | 8 | //each the interface that the garbage collector uses to enumerate the object references is 9 | //typedef void (*foreach_t)( 10 | // void (*cb)(uintptr_t **it, void *ctx), 11 | // void *cb_ctx, 12 | // void *foreach_ctx); 13 | //where foreach_t is the type of the layout function 14 | //such a layout function will be stored in each stack frame and in each heap object 15 | //the garbage collector will then call those functions when it needs to find object references 16 | 17 | //when the gc calls a stack frame layout function it will pass the frame local area address as foreach_ctx 18 | //the layout function can then pass &frame_ptr[index_of_object_ref] to cb. 19 | //cb is provided by the gc and is where it sees the address of the object reference 20 | //cb_ctx is also provided by the gc as a way to get information into cb 21 | 22 | //when the gc calls a heap object layout function the heap object user address is passed as foreach_ctx 23 | interface Function { 24 | fun name(): String 25 | fun declare(): String 26 | fun define(): String 27 | } 28 | 29 | data class CustomLayoutFunction(val layout: List) : Function { 30 | 31 | override fun name(): String { 32 | return "gen_layout${layout.map { i -> i.toString() }.fold("") { acc, s -> "${acc}_$s" }}" 33 | } 34 | 35 | override fun declare(): String { 36 | return "static inline void ${name()}(void (*)(intptr_t **, void *), void *, void *);" 37 | } 38 | 39 | override fun define(): String { 40 | return "static inline void ${name()}(void (*cb)(intptr_t **it, void *ctx), void *cb_ctx, void *foreach_ctx) {\n" + 41 | "\tintptr_t **base_ptr = (intptr_t**)foreach_ctx;\n" + 42 | "\t(void)base_ptr;\n" + 43 | "\t(void)cb;\n" + 44 | "\t(void)cb_ctx;\n" + 45 | layout.map { i -> "\tcb(&base_ptr[${i}], cb_ctx);\n" }.fold("") { acc, s -> "$acc$s" } + 46 | "}\n" 47 | } 48 | } 49 | 50 | object RefArrayLayoutFunction : Function { 51 | 52 | override fun name(): String { 53 | return "gc_layout_ref_array" 54 | } 55 | 56 | override fun declare(): String { 57 | return "static inline void ${name()}(void (*)(intptr_t **, void *), void *, void *);" 58 | } 59 | 60 | override fun define(): String { 61 | //don't have to implement this function it's implemented in gc_interface.h 62 | return "" 63 | } 64 | } 65 | 66 | data class NativeFunction(val id: String) : Function { 67 | override fun name(): String { 68 | return id 69 | } 70 | 71 | override fun declare(): String { 72 | return "void ${name()}(struct vm *);" 73 | } 74 | 75 | override fun define(): String { 76 | //implemented elsewhere 77 | return "" 78 | } 79 | 80 | } -------------------------------------------------------------------------------- /compiler/cka/src/Instruction.kt: -------------------------------------------------------------------------------- 1 | import java.lang.Math.pow 2 | 3 | fun checkSize(i: Long, tc: OutputContext): Boolean { 4 | val max = pow(2.0, (tc.wordSize.toDouble() * 8) - 1) - 1 5 | val min = -pow(2.0, (tc.wordSize.toDouble() * 8) - 1) 6 | return i >= min && i <= max 7 | } 8 | 9 | fun checkSizeByte(i: Long): Boolean { 10 | val max = pow(2.0, 7.0) - 1 11 | val min = -pow(2.0, 7.0) 12 | return i >= min && i <= max 13 | } 14 | 15 | interface Instruction { 16 | fun size(tc: OutputContext): Int 17 | fun emit(pc: ParseContext, oc: OutputContext) 18 | } 19 | 20 | data class SimpleInstruction(val mnemonic: String) : Instruction { 21 | override fun size(tc: OutputContext): Int { 22 | return 1; 23 | } 24 | 25 | override fun emit(pc: ParseContext, oc: OutputContext) { 26 | oc.program.add(oc.convert(mnemonic)) 27 | } 28 | } 29 | 30 | data class LiteralIntInstruction(val mnemonic: String, val data: Long) : Instruction { 31 | 32 | override fun size(tc: OutputContext): Int { 33 | if (checkSizeByte(data)) { 34 | return 2 35 | } else { 36 | return 1 + tc.wordSize 37 | } 38 | } 39 | 40 | override fun emit(pc: ParseContext, oc: OutputContext) { 41 | if (!checkSize(data, oc)) { 42 | //TODO handle this better 43 | throw RuntimeException("literal too large") 44 | } 45 | if (checkSizeByte(data)) { 46 | oc.program.add(oc.convert("${mnemonic}b")) 47 | //I think the following works 48 | oc.program.add(data.toString()) 49 | } else { 50 | oc.program.add(oc.convert(mnemonic)) 51 | oc.program.addAll( 52 | (0 until oc.wordSize) 53 | .map { i -> (data shr i * 8 and 0xFF).toString() } 54 | ) 55 | } 56 | } 57 | } 58 | 59 | data class LiteralStringInstruction(val mnemonic: String, val data: String) : Instruction { 60 | 61 | override fun size(tc: OutputContext): Int { 62 | return 1 + tc.wordSize 63 | } 64 | 65 | override fun emit(pc: ParseContext, oc: OutputContext) { 66 | val stringIndex = oc.addString(data) 67 | if (!checkSize(stringIndex, oc)) { 68 | //TODO handle this better 69 | throw RuntimeException("literal too large") 70 | } 71 | oc.program.add(oc.convert(mnemonic)) 72 | oc.program.addAll( 73 | (0 until oc.wordSize) 74 | .map { i -> (stringIndex shr i * 8 and 0xFF).toString() } 75 | ) 76 | } 77 | } 78 | 79 | //to be used for push Label and jumpxx Label 80 | data class LiteralLabelInstruction(val mnemonic: String, val label: String) : Instruction { 81 | override fun size(tc: OutputContext): Int { 82 | return 1 + tc.wordSize 83 | } 84 | 85 | override fun emit(pc: ParseContext, oc: OutputContext) { 86 | val targetIndex = pc.labels[label]!! 87 | //add the sizes of all the instructions from 0 until targetIndex 88 | val actualTargetIndex = 89 | pc.instructions 90 | .slice(0 until targetIndex) 91 | .map { inst -> inst.size(oc) } 92 | .fold(0) { acc, i -> acc + i } 93 | .toLong() 94 | if (!checkSize(actualTargetIndex, oc)) { 95 | //TODO handle this better 96 | throw RuntimeException("label index too large") 97 | } 98 | oc.program.add(oc.convert(mnemonic)) 99 | oc.program.addAll( 100 | (0 until oc.wordSize) 101 | .map { i -> (actualTargetIndex shr i * 8 and 0xFF).toString() } 102 | ) 103 | } 104 | } 105 | 106 | //layout 107 | //or 108 | //alloc 109 | data class LayoutInstruction(val mnemonic: String, val layout: Function) : Instruction { 110 | 111 | override fun size(tc: OutputContext): Int { 112 | val layoutIndex = tc.addFunction(layout) 113 | return if (checkSizeByte(layoutIndex)) 114 | 2 115 | else 116 | 1 + tc.wordSize 117 | } 118 | 119 | override fun emit(pc: ParseContext, oc: OutputContext) { 120 | val layoutIndex = oc.addFunction(layout) 121 | if (checkSizeByte(layoutIndex)) { 122 | oc.program.add(oc.convert(mnemonic + "b")) 123 | oc.program.add(layoutIndex.toString()) 124 | } else { 125 | oc.program.add(oc.convert(mnemonic)) 126 | oc.program.addAll( 127 | (0 until oc.wordSize) 128 | .map { i -> (layoutIndex shr i * 8 and 0xFF).toString() } 129 | ) 130 | } 131 | } 132 | } 133 | 134 | data class NCallInstruction(val id: String) : Instruction { 135 | override fun size(tc: OutputContext): Int = 136 | 1 + tc.wordSize 137 | 138 | override fun emit(pc: ParseContext, oc: OutputContext) { 139 | val functionIndex = oc.addFunction(NativeFunction(id)) 140 | oc.program.add(oc.convert("ncall")) 141 | oc.program.addAll( 142 | (0 until oc.wordSize) 143 | .map { i -> (functionIndex shr i * 8 and 0xFF).toString() } 144 | ) 145 | } 146 | 147 | } 148 | 149 | -------------------------------------------------------------------------------- /compiler/cka/src/META-INF/MANIFEST.MF: -------------------------------------------------------------------------------- 1 | Manifest-Version: 1.0 2 | Main-Class: MainKt 3 | 4 | -------------------------------------------------------------------------------- /compiler/cka/src/Main.kt: -------------------------------------------------------------------------------- 1 | 2 | fun main(args: Array) { 3 | Cli(args).parse(); 4 | } 5 | -------------------------------------------------------------------------------- /compiler/cka/src/Opcode.kt: -------------------------------------------------------------------------------- 1 | data class Opcode(val value: String) 2 | 3 | -------------------------------------------------------------------------------- /compiler/cka/src/OutputContext.kt: -------------------------------------------------------------------------------- 1 | //represents information about the target code to be generated 2 | data class OutputContext( 3 | //to convert mnemonics from cka grammar to opcodes to store in bytecode array 4 | val convert: (String) -> String, 5 | //sizeof(intptr_t) on target 6 | val wordSize: Int, 7 | //size of heap in units of intptr_t 8 | private val memSize: Int, 9 | //size of stack in units of intptr_t 10 | private val stackSize: Int, 11 | //name of gc impl 12 | private val gcImpl: String, 13 | //array of instructions 14 | val program:ArrayList 15 | ) { 16 | 17 | //where layout functions are stored 18 | private val functions = ArrayList() 19 | 20 | private val strings = ArrayList() 21 | 22 | //adds a function if it is not already present 23 | //returns index of function in function array 24 | fun addFunction(lf: Function): Long { 25 | val ret = functions.indexOf(lf) 26 | if (ret == -1) { 27 | functions.add(lf) 28 | return (functions.size - 1).toLong() 29 | } 30 | return ret.toLong() 31 | } 32 | 33 | fun addString(s: String): Long { 34 | val ret = strings.indexOf(s) 35 | if (ret == -1) { 36 | strings.add(s) 37 | return (strings.size - 1).toLong() 38 | } 39 | return ret.toLong() 40 | } 41 | 42 | //where the program array goes 43 | 44 | fun emit(): String { 45 | return "#include \"vm.h\"\n" + 46 | "#include \"$gcImpl\"\n" + 47 | "\n" + 48 | "#define MEM_SIZE $memSize\n" + 49 | "intptr_t gc_mem[MEM_SIZE];\n" + 50 | "struct gc gc_instance;\n" + 51 | "\n" + 52 | "#define STACK_SIZE $stackSize\n" + 53 | "intptr_t stack_mem[STACK_SIZE];\n" + 54 | "struct vm vm_instance;\n" + 55 | "\n" + 56 | functions.map { f -> f.declare() }.fold("") { acc, s -> "$acc\n$s" } + 57 | "\n" + 58 | functions.map { lf -> lf.define() }.fold("") { acc, s -> "$acc\n$s" } + 59 | "\n" + 60 | "void *functions[] = {\n" + 61 | functions.map { lf -> "\t${lf.name()},\n" }.fold("") { acc, s -> acc + s } + 62 | "\tNULL,\n" + 63 | "};\n\n" + 64 | "uint8_t program[] = {\n" + 65 | program.map { op -> "\t$op,\n" }.fold("") { acc, s -> acc + s } + 66 | "};\n" + 67 | "\n" + 68 | "const char *strings[] = {\n" + 69 | strings.map { s -> "\t\"$s\",\n" }.fold("") { acc, s -> acc + s } + 70 | "\tNULL,\n" + 71 | "};\n" + 72 | "\n" + 73 | "int main(void) {\n" + 74 | "\tgc_init(&gc_instance, gc_mem, MEM_SIZE);\n" + 75 | "\tvm_init(&vm_instance, &gc_instance, stack_mem, functions, strings);\n" + 76 | "\tvm_execute(&vm_instance, program);\n" + 77 | "\treturn 0;\n" + 78 | "}" 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /compiler/cka/src/ParseContext.kt: -------------------------------------------------------------------------------- 1 | class ParseContext { 2 | val labels: MutableMap = HashMap() 3 | val instructions: MutableList = ArrayList() 4 | override fun toString(): String { 5 | return "(ParseContext ${labels.map { me -> "${me.key} : ${me.value}" }} " + 6 | "${instructions.map { i -> i.toString() }}" + 7 | ")" 8 | } 9 | } 10 | 11 | -------------------------------------------------------------------------------- /compiler/ckc/ckc.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /compiler/ckc/gen/ck.interp: -------------------------------------------------------------------------------- 1 | token literal names: 2 | null 3 | 'type' 4 | '=' 5 | '(' 6 | ')' 7 | 'module' 8 | '{' 9 | '}' 10 | '|' 11 | '-' 12 | '!' 13 | '~' 14 | '*' 15 | '/' 16 | '%' 17 | '+' 18 | '<<' 19 | '>>' 20 | '<' 21 | '<=' 22 | '>' 23 | '>=' 24 | '<>' 25 | '==' 26 | '!=' 27 | '&' 28 | '^' 29 | '&&' 30 | '||' 31 | '?' 32 | ':' 33 | 'cfun' 34 | 'let' 35 | 'rec' 36 | 'and' 37 | 'if' 38 | 'else' 39 | ',' 40 | ';' 41 | null 42 | null 43 | null 44 | null 45 | null 46 | 47 | token symbolic names: 48 | null 49 | null 50 | null 51 | null 52 | null 53 | null 54 | null 55 | null 56 | null 57 | null 58 | null 59 | null 60 | null 61 | null 62 | null 63 | null 64 | null 65 | null 66 | null 67 | null 68 | null 69 | null 70 | null 71 | null 72 | null 73 | null 74 | null 75 | null 76 | null 77 | null 78 | null 79 | null 80 | null 81 | null 82 | null 83 | null 84 | null 85 | null 86 | null 87 | NATURAL 88 | TEXT 89 | ID 90 | WHITESPACE 91 | COMMENT 92 | 93 | rule names: 94 | file 95 | decl 96 | sum 97 | product 98 | expr 99 | binding 100 | exprs 101 | sequence 102 | param 103 | params 104 | type 105 | typeParams 106 | types 107 | 108 | 109 | atn: 110 | [3, 24715, 42794, 33075, 47597, 16764, 15335, 30598, 22884, 3, 45, 258, 4, 2, 9, 2, 4, 3, 9, 3, 4, 4, 9, 4, 4, 5, 9, 5, 4, 6, 9, 6, 4, 7, 9, 7, 4, 8, 9, 8, 4, 9, 9, 9, 4, 10, 9, 10, 4, 11, 9, 11, 4, 12, 9, 12, 4, 13, 9, 13, 4, 14, 9, 14, 3, 2, 7, 2, 30, 10, 2, 12, 2, 14, 2, 33, 11, 2, 3, 2, 5, 2, 36, 10, 2, 3, 2, 3, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 5, 3, 45, 10, 3, 3, 3, 5, 3, 48, 10, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 5, 3, 56, 10, 3, 3, 3, 5, 3, 59, 10, 3, 3, 3, 3, 3, 7, 3, 63, 10, 3, 12, 3, 14, 3, 66, 11, 3, 3, 3, 5, 3, 69, 10, 3, 3, 4, 3, 4, 3, 4, 7, 4, 74, 10, 4, 12, 4, 14, 4, 77, 11, 4, 3, 5, 3, 5, 3, 5, 5, 5, 82, 10, 5, 3, 5, 3, 5, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 5, 6, 93, 10, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 5, 6, 103, 10, 6, 3, 6, 3, 6, 3, 6, 5, 6, 108, 10, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 7, 6, 121, 10, 6, 12, 6, 14, 6, 124, 11, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 5, 6, 133, 10, 6, 5, 6, 135, 10, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 5, 6, 179, 10, 6, 3, 6, 7, 6, 182, 10, 6, 12, 6, 14, 6, 185, 11, 6, 3, 7, 3, 7, 3, 7, 5, 7, 190, 10, 7, 3, 7, 3, 7, 3, 7, 3, 8, 3, 8, 3, 8, 7, 8, 198, 10, 8, 12, 8, 14, 8, 201, 11, 8, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 5, 9, 208, 10, 9, 3, 10, 3, 10, 3, 10, 5, 10, 213, 10, 10, 3, 11, 3, 11, 3, 11, 7, 11, 218, 10, 11, 12, 11, 14, 11, 221, 11, 11, 3, 12, 3, 12, 3, 12, 5, 12, 226, 10, 12, 3, 12, 3, 12, 3, 12, 3, 12, 5, 12, 232, 10, 12, 3, 12, 3, 12, 3, 12, 3, 12, 3, 12, 3, 12, 5, 12, 240, 10, 12, 3, 13, 3, 13, 3, 13, 7, 13, 245, 10, 13, 12, 13, 14, 13, 248, 11, 13, 3, 14, 3, 14, 3, 14, 7, 14, 253, 10, 14, 12, 14, 14, 14, 256, 11, 14, 3, 14, 2, 3, 10, 15, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 2, 8, 3, 2, 11, 13, 3, 2, 14, 16, 4, 2, 11, 11, 17, 17, 3, 2, 18, 19, 3, 2, 20, 24, 3, 2, 25, 26, 2, 295, 2, 31, 3, 2, 2, 2, 4, 68, 3, 2, 2, 2, 6, 70, 3, 2, 2, 2, 8, 78, 3, 2, 2, 2, 10, 134, 3, 2, 2, 2, 12, 186, 3, 2, 2, 2, 14, 194, 3, 2, 2, 2, 16, 207, 3, 2, 2, 2, 18, 209, 3, 2, 2, 2, 20, 214, 3, 2, 2, 2, 22, 239, 3, 2, 2, 2, 24, 241, 3, 2, 2, 2, 26, 249, 3, 2, 2, 2, 28, 30, 5, 4, 3, 2, 29, 28, 3, 2, 2, 2, 30, 33, 3, 2, 2, 2, 31, 29, 3, 2, 2, 2, 31, 32, 3, 2, 2, 2, 32, 35, 3, 2, 2, 2, 33, 31, 3, 2, 2, 2, 34, 36, 5, 10, 6, 2, 35, 34, 3, 2, 2, 2, 35, 36, 3, 2, 2, 2, 36, 37, 3, 2, 2, 2, 37, 38, 7, 2, 2, 3, 38, 3, 3, 2, 2, 2, 39, 40, 7, 3, 2, 2, 40, 41, 7, 43, 2, 2, 41, 47, 7, 4, 2, 2, 42, 44, 7, 5, 2, 2, 43, 45, 5, 24, 13, 2, 44, 43, 3, 2, 2, 2, 44, 45, 3, 2, 2, 2, 45, 46, 3, 2, 2, 2, 46, 48, 7, 6, 2, 2, 47, 42, 3, 2, 2, 2, 47, 48, 3, 2, 2, 2, 48, 49, 3, 2, 2, 2, 49, 69, 5, 6, 4, 2, 50, 51, 7, 7, 2, 2, 51, 52, 7, 43, 2, 2, 52, 58, 7, 4, 2, 2, 53, 55, 7, 5, 2, 2, 54, 56, 5, 24, 13, 2, 55, 54, 3, 2, 2, 2, 55, 56, 3, 2, 2, 2, 56, 57, 3, 2, 2, 2, 57, 59, 7, 6, 2, 2, 58, 53, 3, 2, 2, 2, 58, 59, 3, 2, 2, 2, 59, 60, 3, 2, 2, 2, 60, 64, 7, 8, 2, 2, 61, 63, 5, 4, 3, 2, 62, 61, 3, 2, 2, 2, 63, 66, 3, 2, 2, 2, 64, 62, 3, 2, 2, 2, 64, 65, 3, 2, 2, 2, 65, 67, 3, 2, 2, 2, 66, 64, 3, 2, 2, 2, 67, 69, 7, 9, 2, 2, 68, 39, 3, 2, 2, 2, 68, 50, 3, 2, 2, 2, 69, 5, 3, 2, 2, 2, 70, 75, 5, 8, 5, 2, 71, 72, 7, 10, 2, 2, 72, 74, 5, 8, 5, 2, 73, 71, 3, 2, 2, 2, 74, 77, 3, 2, 2, 2, 75, 73, 3, 2, 2, 2, 75, 76, 3, 2, 2, 2, 76, 7, 3, 2, 2, 2, 77, 75, 3, 2, 2, 2, 78, 79, 7, 43, 2, 2, 79, 81, 7, 5, 2, 2, 80, 82, 5, 26, 14, 2, 81, 80, 3, 2, 2, 2, 81, 82, 3, 2, 2, 2, 82, 83, 3, 2, 2, 2, 83, 84, 7, 6, 2, 2, 84, 9, 3, 2, 2, 2, 85, 86, 8, 6, 1, 2, 86, 87, 7, 8, 2, 2, 87, 88, 5, 16, 9, 2, 88, 89, 7, 9, 2, 2, 89, 135, 3, 2, 2, 2, 90, 92, 7, 5, 2, 2, 91, 93, 5, 14, 8, 2, 92, 91, 3, 2, 2, 2, 92, 93, 3, 2, 2, 2, 93, 94, 3, 2, 2, 2, 94, 135, 7, 6, 2, 2, 95, 135, 7, 41, 2, 2, 96, 135, 7, 42, 2, 2, 97, 135, 7, 43, 2, 2, 98, 99, 9, 2, 2, 2, 99, 135, 5, 10, 6, 20, 100, 102, 7, 5, 2, 2, 101, 103, 5, 20, 11, 2, 102, 101, 3, 2, 2, 2, 102, 103, 3, 2, 2, 2, 103, 104, 3, 2, 2, 2, 104, 107, 7, 6, 2, 2, 105, 106, 7, 32, 2, 2, 106, 108, 5, 22, 12, 2, 107, 105, 3, 2, 2, 2, 107, 108, 3, 2, 2, 2, 108, 109, 3, 2, 2, 2, 109, 135, 5, 10, 6, 7, 110, 111, 7, 33, 2, 2, 111, 112, 7, 43, 2, 2, 112, 135, 5, 22, 12, 2, 113, 114, 7, 34, 2, 2, 114, 135, 5, 12, 7, 2, 115, 116, 7, 34, 2, 2, 116, 117, 7, 35, 2, 2, 117, 122, 5, 12, 7, 2, 118, 119, 7, 36, 2, 2, 119, 121, 5, 12, 7, 2, 120, 118, 3, 2, 2, 2, 121, 124, 3, 2, 2, 2, 122, 120, 3, 2, 2, 2, 122, 123, 3, 2, 2, 2, 123, 135, 3, 2, 2, 2, 124, 122, 3, 2, 2, 2, 125, 126, 7, 37, 2, 2, 126, 127, 7, 5, 2, 2, 127, 128, 5, 10, 6, 2, 128, 129, 7, 6, 2, 2, 129, 132, 5, 10, 6, 2, 130, 131, 7, 38, 2, 2, 131, 133, 5, 10, 6, 2, 132, 130, 3, 2, 2, 2, 132, 133, 3, 2, 2, 2, 133, 135, 3, 2, 2, 2, 134, 85, 3, 2, 2, 2, 134, 90, 3, 2, 2, 2, 134, 95, 3, 2, 2, 2, 134, 96, 3, 2, 2, 2, 134, 97, 3, 2, 2, 2, 134, 98, 3, 2, 2, 2, 134, 100, 3, 2, 2, 2, 134, 110, 3, 2, 2, 2, 134, 113, 3, 2, 2, 2, 134, 115, 3, 2, 2, 2, 134, 125, 3, 2, 2, 2, 135, 183, 3, 2, 2, 2, 136, 137, 12, 19, 2, 2, 137, 138, 9, 3, 2, 2, 138, 182, 5, 10, 6, 20, 139, 140, 12, 18, 2, 2, 140, 141, 9, 4, 2, 2, 141, 182, 5, 10, 6, 19, 142, 143, 12, 17, 2, 2, 143, 144, 9, 5, 2, 2, 144, 182, 5, 10, 6, 18, 145, 146, 12, 16, 2, 2, 146, 147, 9, 6, 2, 2, 147, 182, 5, 10, 6, 17, 148, 149, 12, 15, 2, 2, 149, 150, 9, 7, 2, 2, 150, 182, 5, 10, 6, 16, 151, 152, 12, 14, 2, 2, 152, 153, 7, 27, 2, 2, 153, 182, 5, 10, 6, 15, 154, 155, 12, 13, 2, 2, 155, 156, 7, 28, 2, 2, 156, 182, 5, 10, 6, 14, 157, 158, 12, 12, 2, 2, 158, 159, 7, 10, 2, 2, 159, 182, 5, 10, 6, 13, 160, 161, 12, 11, 2, 2, 161, 162, 7, 29, 2, 2, 162, 182, 5, 10, 6, 12, 163, 164, 12, 10, 2, 2, 164, 165, 7, 30, 2, 2, 165, 182, 5, 10, 6, 11, 166, 167, 12, 9, 2, 2, 167, 168, 7, 31, 2, 2, 168, 169, 5, 10, 6, 2, 169, 170, 7, 32, 2, 2, 170, 171, 5, 10, 6, 9, 171, 182, 3, 2, 2, 2, 172, 173, 12, 8, 2, 2, 173, 174, 7, 4, 2, 2, 174, 182, 5, 10, 6, 8, 175, 176, 12, 21, 2, 2, 176, 178, 7, 5, 2, 2, 177, 179, 5, 14, 8, 2, 178, 177, 3, 2, 2, 2, 178, 179, 3, 2, 2, 2, 179, 180, 3, 2, 2, 2, 180, 182, 7, 6, 2, 2, 181, 136, 3, 2, 2, 2, 181, 139, 3, 2, 2, 2, 181, 142, 3, 2, 2, 2, 181, 145, 3, 2, 2, 2, 181, 148, 3, 2, 2, 2, 181, 151, 3, 2, 2, 2, 181, 154, 3, 2, 2, 2, 181, 157, 3, 2, 2, 2, 181, 160, 3, 2, 2, 2, 181, 163, 3, 2, 2, 2, 181, 166, 3, 2, 2, 2, 181, 172, 3, 2, 2, 2, 181, 175, 3, 2, 2, 2, 182, 185, 3, 2, 2, 2, 183, 181, 3, 2, 2, 2, 183, 184, 3, 2, 2, 2, 184, 11, 3, 2, 2, 2, 185, 183, 3, 2, 2, 2, 186, 189, 7, 43, 2, 2, 187, 188, 7, 32, 2, 2, 188, 190, 5, 22, 12, 2, 189, 187, 3, 2, 2, 2, 189, 190, 3, 2, 2, 2, 190, 191, 3, 2, 2, 2, 191, 192, 7, 4, 2, 2, 192, 193, 5, 10, 6, 2, 193, 13, 3, 2, 2, 2, 194, 199, 5, 10, 6, 2, 195, 196, 7, 39, 2, 2, 196, 198, 5, 10, 6, 2, 197, 195, 3, 2, 2, 2, 198, 201, 3, 2, 2, 2, 199, 197, 3, 2, 2, 2, 199, 200, 3, 2, 2, 2, 200, 15, 3, 2, 2, 2, 201, 199, 3, 2, 2, 2, 202, 203, 5, 10, 6, 2, 203, 204, 7, 40, 2, 2, 204, 205, 5, 16, 9, 2, 205, 208, 3, 2, 2, 2, 206, 208, 5, 10, 6, 2, 207, 202, 3, 2, 2, 2, 207, 206, 3, 2, 2, 2, 208, 17, 3, 2, 2, 2, 209, 212, 7, 43, 2, 2, 210, 211, 7, 32, 2, 2, 211, 213, 5, 22, 12, 2, 212, 210, 3, 2, 2, 2, 212, 213, 3, 2, 2, 2, 213, 19, 3, 2, 2, 2, 214, 219, 5, 18, 10, 2, 215, 216, 7, 39, 2, 2, 216, 218, 5, 18, 10, 2, 217, 215, 3, 2, 2, 2, 218, 221, 3, 2, 2, 2, 219, 217, 3, 2, 2, 2, 219, 220, 3, 2, 2, 2, 220, 21, 3, 2, 2, 2, 221, 219, 3, 2, 2, 2, 222, 240, 7, 43, 2, 2, 223, 225, 7, 5, 2, 2, 224, 226, 5, 26, 14, 2, 225, 224, 3, 2, 2, 2, 225, 226, 3, 2, 2, 2, 226, 227, 3, 2, 2, 2, 227, 228, 7, 6, 2, 2, 228, 240, 5, 22, 12, 2, 229, 231, 7, 5, 2, 2, 230, 232, 5, 26, 14, 2, 231, 230, 3, 2, 2, 2, 231, 232, 3, 2, 2, 2, 232, 233, 3, 2, 2, 2, 233, 240, 7, 6, 2, 2, 234, 235, 7, 43, 2, 2, 235, 236, 7, 5, 2, 2, 236, 237, 5, 26, 14, 2, 237, 238, 7, 6, 2, 2, 238, 240, 3, 2, 2, 2, 239, 222, 3, 2, 2, 2, 239, 223, 3, 2, 2, 2, 239, 229, 3, 2, 2, 2, 239, 234, 3, 2, 2, 2, 240, 23, 3, 2, 2, 2, 241, 246, 7, 43, 2, 2, 242, 243, 7, 39, 2, 2, 243, 245, 7, 43, 2, 2, 244, 242, 3, 2, 2, 2, 245, 248, 3, 2, 2, 2, 246, 244, 3, 2, 2, 2, 246, 247, 3, 2, 2, 2, 247, 25, 3, 2, 2, 2, 248, 246, 3, 2, 2, 2, 249, 254, 5, 22, 12, 2, 250, 251, 7, 39, 2, 2, 251, 253, 5, 22, 12, 2, 252, 250, 3, 2, 2, 2, 253, 256, 3, 2, 2, 2, 254, 252, 3, 2, 2, 2, 254, 255, 3, 2, 2, 2, 255, 27, 3, 2, 2, 2, 256, 254, 3, 2, 2, 2, 31, 31, 35, 44, 47, 55, 58, 64, 68, 75, 81, 92, 102, 107, 122, 132, 134, 178, 181, 183, 189, 199, 207, 212, 219, 225, 231, 239, 246, 254] -------------------------------------------------------------------------------- /compiler/ckc/gen/ck.tokens: -------------------------------------------------------------------------------- 1 | T__0=1 2 | T__1=2 3 | T__2=3 4 | T__3=4 5 | T__4=5 6 | T__5=6 7 | T__6=7 8 | T__7=8 9 | T__8=9 10 | T__9=10 11 | T__10=11 12 | T__11=12 13 | T__12=13 14 | T__13=14 15 | T__14=15 16 | T__15=16 17 | T__16=17 18 | T__17=18 19 | T__18=19 20 | T__19=20 21 | T__20=21 22 | T__21=22 23 | T__22=23 24 | T__23=24 25 | T__24=25 26 | T__25=26 27 | T__26=27 28 | T__27=28 29 | T__28=29 30 | T__29=30 31 | T__30=31 32 | T__31=32 33 | T__32=33 34 | T__33=34 35 | T__34=35 36 | T__35=36 37 | T__36=37 38 | T__37=38 39 | NATURAL=39 40 | TEXT=40 41 | ID=41 42 | WHITESPACE=42 43 | COMMENT=43 44 | 'type'=1 45 | '='=2 46 | '('=3 47 | ')'=4 48 | 'module'=5 49 | '{'=6 50 | '}'=7 51 | '|'=8 52 | '-'=9 53 | '!'=10 54 | '~'=11 55 | '*'=12 56 | '/'=13 57 | '%'=14 58 | '+'=15 59 | '<<'=16 60 | '>>'=17 61 | '<'=18 62 | '<='=19 63 | '>'=20 64 | '>='=21 65 | '<>'=22 66 | '=='=23 67 | '!='=24 68 | '&'=25 69 | '^'=26 70 | '&&'=27 71 | '||'=28 72 | '?'=29 73 | ':'=30 74 | 'cfun'=31 75 | 'let'=32 76 | 'rec'=33 77 | 'and'=34 78 | 'if'=35 79 | 'else'=36 80 | ','=37 81 | ';'=38 82 | -------------------------------------------------------------------------------- /compiler/ckc/gen/ckLexer.tokens: -------------------------------------------------------------------------------- 1 | T__0=1 2 | T__1=2 3 | T__2=3 4 | T__3=4 5 | T__4=5 6 | T__5=6 7 | T__6=7 8 | T__7=8 9 | T__8=9 10 | T__9=10 11 | T__10=11 12 | T__11=12 13 | T__12=13 14 | T__13=14 15 | T__14=15 16 | T__15=16 17 | T__16=17 18 | T__17=18 19 | T__18=19 20 | T__19=20 21 | T__20=21 22 | T__21=22 23 | T__22=23 24 | T__23=24 25 | T__24=25 26 | T__25=26 27 | T__26=27 28 | T__27=28 29 | T__28=29 30 | T__29=30 31 | T__30=31 32 | T__31=32 33 | T__32=33 34 | T__33=34 35 | T__34=35 36 | T__35=36 37 | T__36=37 38 | T__37=38 39 | NATURAL=39 40 | TEXT=40 41 | ID=41 42 | WHITESPACE=42 43 | COMMENT=43 44 | 'type'=1 45 | '='=2 46 | '('=3 47 | ')'=4 48 | 'module'=5 49 | '{'=6 50 | '}'=7 51 | '|'=8 52 | '-'=9 53 | '!'=10 54 | '~'=11 55 | '*'=12 56 | '/'=13 57 | '%'=14 58 | '+'=15 59 | '<<'=16 60 | '>>'=17 61 | '<'=18 62 | '<='=19 63 | '>'=20 64 | '>='=21 65 | '<>'=22 66 | '=='=23 67 | '!='=24 68 | '&'=25 69 | '^'=26 70 | '&&'=27 71 | '||'=28 72 | '?'=29 73 | ':'=30 74 | 'cfun'=31 75 | 'let'=32 76 | 'rec'=33 77 | 'and'=34 78 | 'if'=35 79 | 'else'=36 80 | ','=37 81 | ';'=38 82 | -------------------------------------------------------------------------------- /compiler/ckc/grammar/ck.g4: -------------------------------------------------------------------------------- 1 | 2 | 3 | grammar ck; 4 | 5 | //basic CK 6 | 7 | file 8 | : decl* expr? EOF 9 | ; 10 | 11 | decl 12 | : 'type' ID '=' ('(' typeParams? ')')? sum #typeDecl 13 | | 'module' ID '=' ('(' typeParams? ')')? '{' decl* '}' #moduleDecl 14 | ; 15 | 16 | typeParams 17 | : ID ( ',' ID )* 18 | ; 19 | 20 | sum 21 | : product ( '|' product )* 22 | ; 23 | 24 | product 25 | : ID '(' types? ')' 26 | ; 27 | 28 | expr 29 | : '{' sequence '}' #sequenceExpr 30 | | '(' exprs? ')' #tupleExpr 31 | | NATURAL #naturalExpr 32 | | TEXT #textExpr 33 | | ID #refExpr 34 | | expr '(' exprs? ')' #applyExpr 35 | | op=( '-' | '!' | '~' ) expr #unaryExpr 36 | | lhs=expr op=( '*' | '/' | '%' ) rhs=expr #multExpr 37 | | lhs=expr op=( '+' | '-' ) rhs=expr #addExpr 38 | | lhs=expr op=( '<<' | '>>' ) rhs=expr #shiftExpr 39 | | lhs=expr op=( '<' | '<=' | '>' | '>=' | '<>' ) rhs=expr #relExpr 40 | | lhs=expr op=( '==' | '!=' ) rhs=expr #equalityExpr 41 | | lhs=expr '&' rhs=expr #bitAndExpr 42 | | lhs=expr '^' rhs=expr #bitXorExpr 43 | | lhs=expr '|' rhs=expr #bitOrExpr 44 | | lhs=expr '&&' rhs=expr #andExpr 45 | | lhs=expr '||' rhs=expr #orExpr 46 | | cond=expr '?' con=expr ':' alt=expr #condExpr 47 | | target=expr '=' value=expr #assignExpr 48 | | '(' params? ')' (':' type)? expr #funExpr 49 | | 'cfun' ID type #cFunExpr 50 | | 'let' binding #letExpr 51 | | 'let' 'rec' binding ('and' binding)* #letRecExpr 52 | | 'if' '(' cond=expr ')' csq=expr ( 'else' alt=expr )? #ifExpr 53 | ; 54 | 55 | binding 56 | : ID (':' type)? '=' expr 57 | ; 58 | 59 | exprs 60 | : expr (',' expr)* 61 | ; 62 | 63 | sequence 64 | : expr ';' sequence 65 | | expr 66 | ; 67 | 68 | param 69 | : ID (':' type)? 70 | ; 71 | 72 | params 73 | : param ( ',' param )* 74 | ; 75 | 76 | type 77 | : ID #simpleType 78 | | '(' types? ')' type #funType 79 | | '(' types? ')' #tupleType 80 | | ID '(' types ')' #ctorType 81 | ; 82 | 83 | types 84 | : type ( ',' type )* 85 | ; 86 | 87 | NATURAL : ('0'..'9')+ ; 88 | 89 | TEXT 90 | : '"' ( EscapeSequence | ~('\\'|'"') )* '"' 91 | ; 92 | 93 | fragment 94 | EscapeSequence 95 | : '\\' ('b'|'t'|'n'|'f'|'r'|'"'|'\\') 96 | | HexEscape 97 | | UnicodeEscape 98 | ; 99 | 100 | fragment 101 | HexDigit : ('0'..'9'|'a'..'f'|'A'..'F') ; 102 | 103 | fragment 104 | HexEscape : '\\' 'x' HexDigit HexDigit ; 105 | 106 | fragment 107 | UnicodeEscape 108 | : '\\' 'u' HexDigit HexDigit HexDigit HexDigit 109 | | '\\' 'u' HexDigit HexDigit HexDigit HexDigit HexDigit HexDigit HexDigit HexDigit 110 | ; 111 | 112 | ID 113 | : ('_'|'a'..'z'|'A'..'Z') ('_'|'0'..'9'|'a'..'z'|'A'..'Z')* 114 | | '`' ~('`')+ '`' 115 | ; 116 | 117 | WHITESPACE : (' '|'\t'|'\u000C'|'\n'|'\r') -> skip ; 118 | COMMENT : '//' ~('\n'|'\r')* '\r'? '\n' -> skip ; 119 | -------------------------------------------------------------------------------- /compiler/ckc/src/META-INF/MANIFEST.MF: -------------------------------------------------------------------------------- 1 | Manifest-Version: 1.0 2 | Main-Class: ck.MainKt 3 | 4 | -------------------------------------------------------------------------------- /compiler/ckc/src/ck/Cli.kt: -------------------------------------------------------------------------------- 1 | package ck 2 | 3 | import ck.analyze.Analyze 4 | import ck.ast.visitors.CompilationVisitor 5 | import ck.ast.visitors.ComputeCapturesVisitor 6 | import ck.ast.visitors.FindTailCalls 7 | import ck.ast.visitors.ScopeLinkingVisitor 8 | import ck.grammar.Parse 9 | import org.antlr.v4.runtime.CharStreams 10 | import org.apache.commons.cli.* 11 | import util.extensions.toDelimitedString 12 | import java.io.File 13 | 14 | class Cli(val args: Array) { 15 | 16 | private val options = Options() 17 | 18 | init { 19 | options.addOption("h", "help", false, "show help") 20 | options.addRequiredOption("i", "input", true, "input file") 21 | options.addOption("o", "output", true, "output file") 22 | options.addOption("d", "debug", false, "generate debug strings") 23 | } 24 | 25 | fun parse() { 26 | 27 | val cliParser = DefaultParser() 28 | 29 | val cmd: CommandLine? 30 | try { 31 | cmd = cliParser.parse(options, args) 32 | 33 | if (cmd!!.hasOption("h")) { 34 | help() 35 | } else { 36 | 37 | val inputFileName = cmd.getOptionValue("i")!! 38 | val outputFileName = cmd.getOptionValue("o") 39 | val debug = cmd.hasOption("d") 40 | 41 | val stream = CharStreams.fromFileName(inputFileName) 42 | 43 | Parse.file(stream).map( 44 | { err -> 45 | //parse error 46 | println("$err\n") 47 | }, 48 | { file -> 49 | //check types 50 | Analyze.analyze(file.expr, null, null) 51 | //find tail calls 52 | file.accept(FindTailCalls()) 53 | //link scopes 54 | file.accept(ScopeLinkingVisitor()) 55 | //compute function captures 56 | file.accept(ComputeCapturesVisitor()) 57 | //compile file 58 | val code: List = file.accept(CompilationVisitor(debug)) 59 | //determine output location 60 | if (outputFileName != null) { 61 | File(outputFileName).printWriter().use { out -> 62 | out.print(code.toDelimitedString("\n")) 63 | } 64 | } else { 65 | println(code.toDelimitedString("\n")) 66 | } 67 | } 68 | ) 69 | } 70 | 71 | } catch (e: ParseException) { 72 | help() 73 | } catch (e: RuntimeException) { 74 | e.printStackTrace() 75 | } 76 | 77 | } 78 | 79 | private fun help() { 80 | // This prints out some help 81 | HelpFormatter().printHelp("h", options) 82 | } 83 | } 84 | 85 | -------------------------------------------------------------------------------- /compiler/ckc/src/ck/Main.kt: -------------------------------------------------------------------------------- 1 | package ck 2 | 3 | fun main(args: Array) { 4 | Cli(args).parse() 5 | } 6 | 7 | -------------------------------------------------------------------------------- /compiler/ckc/src/ck/ast/Type.kt: -------------------------------------------------------------------------------- 1 | package ck.ast 2 | 3 | import util.extensions.toDelimitedString 4 | 5 | //Types 6 | 7 | sealed class Type { 8 | 9 | abstract fun isPolyType(): Boolean 10 | 11 | companion object { 12 | 13 | var i = 0 14 | 15 | fun newId(): String = 16 | "${i++}" 17 | 18 | fun newVar(): Var = 19 | Var(newId()) 20 | 21 | //take a type and return a simple version of it 22 | //where vars have been replaced by their instances 23 | fun simplify(t: Type): Type = 24 | when { 25 | t is Var && t.instance == null -> t 26 | t is Var -> simplify(t.instance!!) 27 | t is Op -> Op( 28 | t.operator, 29 | t.params.map { p -> simplify(p) }) 30 | else -> t 31 | } 32 | 33 | //takes a simplified type for t1 and t2, 34 | //returns a list of substitutions formed by 35 | //associating Vars in t1 with matching types in t2 36 | fun getSubstitutions(t1: Type, t2: Type): Set> = 37 | when { 38 | t1 is Var -> setOf(Pair(t1.id, t2)) 39 | t1 is Op && t2 is Op && t1.params.size == t2.params.size -> 40 | t1.params.zip(t2.params).flatMap { p -> getSubstitutions(p.first, p.second) }.toSet() 41 | else -> emptySet() 42 | } 43 | 44 | //takes substitutions from getSubstitutions and applies them to a simplified type t 45 | fun apply(subs: Set>, t: Type): Type = 46 | when (t) { 47 | is Var -> { 48 | val found = subs.find { p -> p.first == t.id } 49 | found?.second ?: t 50 | } 51 | is Op -> Op( 52 | t.operator, 53 | t.params.map { p -> apply(subs, p) }) 54 | } 55 | 56 | } 57 | 58 | // data class Rec(val param: String, val body: Type): Type() { 59 | // override fun isPolyType(): Boolean = true 60 | // 61 | // } 62 | 63 | data class Var(val id: String) : Type() { 64 | //TODO: eliminate instance and store type var assignments in env 65 | 66 | var instance: Type? = null 67 | 68 | override fun isPolyType(): Boolean = 69 | if (instance == null) 70 | true 71 | else 72 | instance!!.isPolyType() 73 | 74 | override fun toString(): String = 75 | if (instance != null) "($id = $instance)" 76 | else id 77 | 78 | } 79 | 80 | data class Op(val operator: String, val params: List) : Type() { 81 | 82 | constructor(operator: String) : this(operator, emptyList()) 83 | 84 | override fun isPolyType(): Boolean = params.any { p -> p.isPolyType() } 85 | 86 | override fun toString(): String = 87 | when { 88 | operator == "Fun" -> "(${params.take(params.size - 1).toDelimitedString(", ")}): ${params.last()}" 89 | operator == "Tuple" && params.isEmpty() -> "()" 90 | else -> "$operator(${params.toDelimitedString(", ")})" 91 | } 92 | } 93 | 94 | } -------------------------------------------------------------------------------- /compiler/ckc/src/ck/ast/node/ASTNode.kt: -------------------------------------------------------------------------------- 1 | package ck.ast.node 2 | 3 | import ck.ast.visitors.ASTVisitor 4 | 5 | interface ASTNode { 6 | fun accept(visitor: ASTVisitor): T 7 | } 8 | 9 | open class BaseASTNode : ASTNode { 10 | override fun accept(visitor: ASTVisitor): T { 11 | TODO("not implemented") 12 | } 13 | } 14 | 15 | -------------------------------------------------------------------------------- /compiler/ckc/src/ck/ast/node/CkFile.kt: -------------------------------------------------------------------------------- 1 | package ck.ast.node 2 | 3 | import ck.ast.visitors.ASTVisitor 4 | 5 | class CkFile(val decls: List, val expr: Expr) : BaseASTNode() { 6 | 7 | override fun accept(visitor: ASTVisitor): T = 8 | visitor.visit(this) 9 | 10 | } 11 | 12 | -------------------------------------------------------------------------------- /compiler/ckc/src/ck/ast/node/Decl.kt: -------------------------------------------------------------------------------- 1 | package ck.ast.node 2 | 3 | import ck.ast.visitors.ASTVisitor 4 | 5 | sealed class Decl: BaseASTNode() { 6 | 7 | data class Module(val id: String, val params: List, val decls: List): Decl() { 8 | override fun accept(visitor: ASTVisitor): T { 9 | return visitor.visit(this) 10 | } 11 | } 12 | 13 | data class Type(val id: String, val params: List, val sum: Sum): Decl() { 14 | 15 | data class Sum(val products: List) 16 | 17 | data class Product(val id: String, val types: List) 18 | 19 | override fun accept(visitor: ASTVisitor): T { 20 | return visitor.visit(this) 21 | } 22 | } 23 | 24 | } -------------------------------------------------------------------------------- /compiler/ckc/src/ck/ast/visitors/ASTVisitor.kt: -------------------------------------------------------------------------------- 1 | package ck.ast.visitors 2 | 3 | import ck.ast.node.CkFile 4 | import ck.ast.node.Decl 5 | import ck.ast.node.Expr 6 | 7 | interface ASTVisitor { 8 | 9 | fun visit(f: CkFile): T 10 | 11 | fun visit(m: Decl.Module): T 12 | fun visit(m: Decl.Type): T 13 | 14 | fun visit(e: Expr.Tuple): T 15 | fun visit(e: Expr.Sequence): T 16 | fun visit(e: Expr.Natural): T 17 | fun visit(e: Expr.Ref): T 18 | fun visit(e: Expr.Apply): T 19 | fun visit(e: Expr.Unary): T 20 | fun visit(e: Expr.Binary): T 21 | fun visit(e: Expr.Cond): T 22 | fun visit(e: Expr.Assign): T 23 | fun visit(e: Expr.Fun): T 24 | fun visit(e: Expr.Fun.DataConstructor): T 25 | fun visit(e: Expr.Fun.DataPredicate): T 26 | fun visit(e: Expr.Fun.DataAccessor): T 27 | fun visit(e: Expr.CFun): T 28 | fun visit(e: Expr.Let): T 29 | fun visit(e: Expr.Let.Rec): T 30 | fun visit(e: Expr.If): T 31 | } 32 | 33 | open class BaseASTVisitor : ASTVisitor { 34 | override fun visit(m: Decl.Type): T { 35 | TODO("not implemented") //To change body of created functions use File | Settings | File Templates. 36 | } 37 | 38 | override fun visit(m: Decl.Module): T { 39 | TODO("not implemented") //To change body of created functions use File | Settings | File Templates. 40 | } 41 | 42 | override fun visit(e: Expr.Fun.DataPredicate): T { 43 | TODO("not implemented") //To change body of created functions use File | Settings | File Templates. 44 | } 45 | 46 | override fun visit(e: Expr.Fun.DataAccessor): T { 47 | TODO("not implemented") //To change body of created functions use File | Settings | File Templates. 48 | } 49 | 50 | override fun visit(e: Expr.Fun.DataConstructor): T { 51 | TODO("not implemented") //To change body of created functions use File | Settings | File Templates. 52 | } 53 | 54 | override fun visit(e: Expr.Let.Rec): T { 55 | TODO("not implemented") //To change body of created functions use File | Settings | File Templates. 56 | } 57 | 58 | override fun visit(f: CkFile): T { 59 | TODO("not implemented") //To change body of created functions use File | Settings | File Templates. 60 | } 61 | 62 | override fun visit(e: Expr.Tuple): T { 63 | TODO("not implemented") //To change body of created functions use File | Settings | File Templates. 64 | } 65 | 66 | override fun visit(e: Expr.Sequence): T { 67 | TODO("not implemented") //To change body of created functions use File | Settings | File Templates. 68 | } 69 | 70 | override fun visit(e: Expr.Natural): T { 71 | TODO("not implemented") //To change body of created functions use File | Settings | File Templates. 72 | } 73 | 74 | override fun visit(e: Expr.Ref): T { 75 | TODO("not implemented") //To change body of created functions use File | Settings | File Templates. 76 | } 77 | 78 | override fun visit(e: Expr.Apply): T { 79 | TODO("not implemented") //To change body of created functions use File | Settings | File Templates. 80 | } 81 | 82 | override fun visit(e: Expr.Unary): T { 83 | TODO("not implemented") //To change body of created functions use File | Settings | File Templates. 84 | } 85 | 86 | override fun visit(e: Expr.Binary): T { 87 | TODO("not implemented") //To change body of created functions use File | Settings | File Templates. 88 | } 89 | 90 | override fun visit(e: Expr.Cond): T { 91 | TODO("not implemented") //To change body of created functions use File | Settings | File Templates. 92 | } 93 | 94 | override fun visit(e: Expr.Assign): T { 95 | TODO("not implemented") //To change body of created functions use File | Settings | File Templates. 96 | } 97 | 98 | override fun visit(e: Expr.Fun): T { 99 | TODO("not implemented") //To change body of created functions use File | Settings | File Templates. 100 | } 101 | 102 | override fun visit(e: Expr.CFun): T { 103 | TODO("not implemented") //To change body of created functions use File | Settings | File Templates. 104 | } 105 | 106 | override fun visit(e: Expr.Let): T { 107 | TODO("not implemented") //To change body of created functions use File | Settings | File Templates. 108 | } 109 | 110 | override fun visit(e: Expr.If): T { 111 | TODO("not implemented") //To change body of created functions use File | Settings | File Templates. 112 | } 113 | 114 | } -------------------------------------------------------------------------------- /compiler/ckc/src/ck/ast/visitors/ComputeCapturesVisitor.kt: -------------------------------------------------------------------------------- 1 | package ck.ast.visitors 2 | 3 | import ck.ast.node.CkFile 4 | import ck.ast.node.Expr 5 | 6 | class ComputeCapturesVisitor : BaseASTVisitor() { 7 | 8 | var currentFun: Expr.Fun? = null 9 | 10 | override fun visit(e: Expr.Fun.DataPredicate) { 11 | //nothing 12 | } 13 | 14 | override fun visit(e: Expr.Fun.DataAccessor) { 15 | //nothing 16 | } 17 | 18 | override fun visit(e: Expr.Fun.DataConstructor) { 19 | //nothing 20 | } 21 | 22 | override fun visit(f: CkFile) { 23 | f.expr.accept(this) 24 | } 25 | 26 | override fun visit(e: Expr.Tuple) { 27 | e.exprs.forEach { expr -> expr.accept(this) } 28 | } 29 | 30 | override fun visit(e: Expr.Sequence) { 31 | e.first.accept(this) 32 | e.second.accept(this) 33 | } 34 | 35 | override fun visit(e: Expr.Natural) { 36 | //nothing 37 | } 38 | 39 | override fun visit(e: Expr.Ref) { 40 | val def = e.accept(GetDefinitionVisitor()) 41 | //create capture expr 42 | val capture = Expr.Ref(e.id, e.t) 43 | capture.enclosingScope = currentFun?.enclosingScope 44 | when { 45 | //if def is non isLocal then add capture to currentFun 46 | def is Definition && !def.local -> { 47 | //currentFun can't be null here, right? 48 | //as long as GetTypeVisitor returned non ErrorType on the program 49 | currentFun!!.captures.add(capture) 50 | } 51 | } 52 | } 53 | 54 | override fun visit(e: Expr.Apply) { 55 | e.args.forEach { a -> a.accept(this) } 56 | e.fn.accept(this) 57 | } 58 | 59 | override fun visit(e: Expr.Unary) { 60 | e.operand.accept(this) 61 | } 62 | 63 | override fun visit(e: Expr.Binary) { 64 | e.lhs.accept(this) 65 | e.rhs.accept(this) 66 | } 67 | 68 | override fun visit(e: Expr.Cond) { 69 | e.cond.accept(this) 70 | e.csq.accept(this) 71 | e.alt.accept(this) 72 | } 73 | 74 | override fun visit(e: Expr.Assign) { 75 | e.target.accept(this) 76 | e.value.accept(this) 77 | } 78 | 79 | override fun visit(e: Expr.Fun) { 80 | //save current fun 81 | val lastFun = currentFun 82 | //set current fun to e 83 | currentFun = e 84 | //compute captures for e 85 | e.body.accept(this) 86 | //reset current fun 87 | currentFun = lastFun 88 | //do a pass on any captures from e, to add to current fun if necessary 89 | e.captures.forEach { c -> c.accept(this) } 90 | } 91 | 92 | override fun visit(e: Expr.CFun) { 93 | //nothing 94 | } 95 | 96 | override fun visit(e: Expr.Let) { 97 | e.binding.value.accept(this) 98 | e.body.accept(this) 99 | } 100 | 101 | override fun visit(e: Expr.Let.Rec) { 102 | e.bindings.forEach { b -> b.value.accept(this) } 103 | e.body.accept(this) 104 | } 105 | 106 | override fun visit(e: Expr.If) { 107 | e.cond.accept(this) 108 | e.csq.accept(this) 109 | e.alt?.accept(this) 110 | } 111 | 112 | } 113 | 114 | -------------------------------------------------------------------------------- /compiler/ckc/src/ck/ast/visitors/FindTailCalls.kt: -------------------------------------------------------------------------------- 1 | package ck.ast.visitors 2 | 3 | import ck.ast.node.CkFile 4 | import ck.ast.node.Expr 5 | 6 | class FindTailCalls: BaseASTVisitor() { 7 | 8 | var tailPosition = false 9 | 10 | override fun visit(e: Expr.Fun.DataPredicate) { 11 | //nothing 12 | } 13 | 14 | override fun visit(e: Expr.Fun.DataConstructor) { 15 | //nothing 16 | } 17 | 18 | override fun visit(e: Expr.Fun.DataAccessor) { 19 | //nothing 20 | } 21 | 22 | override fun visit(e: Expr.Let.Rec) { 23 | val tp = tailPosition 24 | tailPosition = false 25 | e.bindings.forEach { b -> b.value.accept(this) } 26 | tailPosition = tp 27 | e.body.accept(this) 28 | } 29 | 30 | override fun visit(f: CkFile) { 31 | tailPosition = false 32 | f.expr.accept(this) 33 | } 34 | 35 | override fun visit(e: Expr.Tuple) { 36 | val tp = tailPosition 37 | tailPosition = false 38 | e.exprs.forEach { expr -> expr.accept(this) } 39 | tailPosition = tp 40 | } 41 | 42 | override fun visit(e: Expr.Sequence) { 43 | val tp = tailPosition 44 | tailPosition = false 45 | e.first.accept(this) 46 | tailPosition = tp 47 | e.second.accept(this) 48 | } 49 | 50 | override fun visit(e: Expr.Natural) { 51 | //nothing 52 | } 53 | 54 | override fun visit(e: Expr.Ref) { 55 | //nothing 56 | } 57 | 58 | override fun visit(e: Expr.Apply) { 59 | e.isTailCall = tailPosition 60 | tailPosition = false 61 | e.args.forEach { a -> a.accept(this) } 62 | e.fn.accept(this) 63 | tailPosition = e.isTailCall 64 | } 65 | 66 | override fun visit(e: Expr.Unary) { 67 | val tp = tailPosition 68 | tailPosition = false 69 | e.operand.accept(this) 70 | tailPosition = tp 71 | } 72 | 73 | override fun visit(e: Expr.Binary) { 74 | val tp = tailPosition 75 | tailPosition = false 76 | e.lhs.accept(this) 77 | e.rhs.accept(this) 78 | tailPosition = tp 79 | } 80 | 81 | override fun visit(e: Expr.Cond) { 82 | val tp = tailPosition 83 | tailPosition = false 84 | e.cond.accept(this) 85 | tailPosition = tp 86 | e.csq.accept(this) 87 | e.alt.accept(this) 88 | } 89 | 90 | override fun visit(e: Expr.Assign) { 91 | TODO("not implemented") 92 | } 93 | 94 | override fun visit(e: Expr.Fun) { 95 | val tp = tailPosition 96 | tailPosition = true 97 | e.body.accept(this) 98 | tailPosition = tp 99 | } 100 | 101 | override fun visit(e: Expr.CFun) { 102 | //nothing 103 | } 104 | 105 | override fun visit(e: Expr.Let) { 106 | val tp = tailPosition 107 | tailPosition = false 108 | e.binding.value.accept(this) 109 | tailPosition = tp 110 | e.body.accept(this) 111 | } 112 | 113 | override fun visit(e: Expr.If) { 114 | val tp = tailPosition 115 | tailPosition = false 116 | e.cond.accept(this) 117 | tailPosition = tp 118 | e.csq.accept(this) 119 | e.alt?.accept(this) 120 | } 121 | 122 | } -------------------------------------------------------------------------------- /compiler/ckc/src/ck/ast/visitors/GetDefinitionVisitor.kt: -------------------------------------------------------------------------------- 1 | package ck.ast.visitors 2 | 3 | import ck.ast.node.CkFile 4 | import ck.ast.node.Expr 5 | 6 | sealed class Definition(val local: Boolean) { 7 | class Let(val node: Expr.Let, local: Boolean) : Definition(local) 8 | class LetRec(val node: Expr.Let.Rec, local: Boolean): Definition(local) 9 | class Param(val node: Expr.Fun.Param, local: Boolean) : Definition(local) 10 | } 11 | 12 | //a visitor used to traverse the ast using enclosing 13 | //scope to find the definition of a ck.ast.node.Expr.Ref 14 | class GetDefinitionVisitor : BaseASTVisitor() { 15 | 16 | var isLocal = true 17 | 18 | var id: String? = null 19 | 20 | override fun visit(e: Expr.Fun.DataPredicate): Definition? { 21 | return null 22 | } 23 | 24 | override fun visit(e: Expr.Fun.DataAccessor): Definition? { 25 | return null 26 | } 27 | 28 | override fun visit(e: Expr.Fun.DataConstructor): Definition? { 29 | return null 30 | } 31 | 32 | override fun visit(f: CkFile): Definition? { 33 | return null 34 | } 35 | 36 | override fun visit(e: Expr.Tuple): Definition? { 37 | return null 38 | } 39 | 40 | override fun visit(e: Expr.Sequence): Definition? { 41 | return null 42 | } 43 | 44 | override fun visit(e: Expr.Natural): Definition? { 45 | return null 46 | } 47 | 48 | //first visit should be to a ck.ast.node.Expr.Ref where we immediately 49 | //start visiting enclosing scopes 50 | override fun visit(e: Expr.Ref): Definition? { 51 | id = e.id 52 | return e.enclosingScope?.accept(this) 53 | } 54 | 55 | override fun visit(e: Expr.Apply): Definition? { 56 | return null 57 | } 58 | 59 | override fun visit(e: Expr.Unary): Definition? { 60 | return null 61 | } 62 | 63 | override fun visit(e: Expr.Binary): Definition? { 64 | return null 65 | } 66 | 67 | override fun visit(e: Expr.Cond): Definition? { 68 | return null 69 | } 70 | 71 | override fun visit(e: Expr.Assign): Definition? { 72 | return null 73 | } 74 | 75 | override fun visit(e: Expr.Fun): Definition? { 76 | //look at function parameters for id 77 | for (param in e.params) { 78 | if (param.id == id) { 79 | return Definition.Param(param, isLocal) 80 | } 81 | } 82 | isLocal = false 83 | //otherwise look in enclosing scope 84 | return e.enclosingScope?.accept(this) 85 | } 86 | 87 | override fun visit(e: Expr.Let): Definition? { 88 | //check the id of ck.ast.node.Expr.Let 89 | if (e.binding.id == id) { 90 | return Definition.Let(e, isLocal) 91 | } 92 | //otherwise look in enclosing scope 93 | return e.enclosingScope?.accept(this) 94 | } 95 | 96 | override fun visit(e: Expr.Let.Rec): Definition? { 97 | for (binding in e.bindings) { 98 | if (binding.id == id) { 99 | return Definition.LetRec(e, isLocal) 100 | } 101 | } 102 | return e.enclosingScope?.accept(this) 103 | } 104 | 105 | override fun visit(e: Expr.CFun): Definition? { 106 | return null 107 | } 108 | 109 | override fun visit(e: Expr.If): Definition? { 110 | return null 111 | } 112 | 113 | } -------------------------------------------------------------------------------- /compiler/ckc/src/ck/ast/visitors/GetEnclosingFunction.kt: -------------------------------------------------------------------------------- 1 | package ck.ast.visitors 2 | 3 | import ck.ast.node.CkFile 4 | import ck.ast.node.Expr 5 | 6 | class GetEnclosingFunction : BaseASTVisitor() { 7 | 8 | override fun visit(e: Expr.Fun.DataPredicate): Expr.Fun? { 9 | return null 10 | } 11 | 12 | override fun visit(e: Expr.Fun.DataConstructor): Expr.Fun? { 13 | return null 14 | } 15 | 16 | override fun visit(e: Expr.CFun): Expr.Fun? { 17 | return null 18 | } 19 | 20 | override fun visit(e: Expr.Fun.DataAccessor): Expr.Fun? { 21 | return null 22 | } 23 | 24 | override fun visit(f: CkFile): Expr.Fun? { 25 | return null 26 | } 27 | 28 | override fun visit(e: Expr.Tuple): Expr.Fun? { 29 | return e.enclosingScope?.accept(this) 30 | } 31 | 32 | override fun visit(e: Expr.Sequence): Expr.Fun? { 33 | return e.enclosingScope?.accept(this) 34 | } 35 | 36 | override fun visit(e: Expr.Natural): Expr.Fun? { 37 | return e.enclosingScope?.accept(this) 38 | } 39 | 40 | override fun visit(e: Expr.Ref): Expr.Fun? { 41 | return e.enclosingScope?.accept(this) 42 | } 43 | 44 | override fun visit(e: Expr.Apply): Expr.Fun? { 45 | return e.enclosingScope?.accept(this) 46 | } 47 | 48 | override fun visit(e: Expr.Unary): Expr.Fun? { 49 | return e.enclosingScope?.accept(this) 50 | } 51 | 52 | override fun visit(e: Expr.Binary): Expr.Fun? { 53 | return e.enclosingScope?.accept(this) 54 | } 55 | 56 | override fun visit(e: Expr.Cond): Expr.Fun? { 57 | return e.enclosingScope?.accept(this) 58 | } 59 | 60 | override fun visit(e: Expr.Assign): Expr.Fun? { 61 | return e.enclosingScope?.accept(this) 62 | } 63 | 64 | override fun visit(e: Expr.Fun): Expr.Fun? { 65 | return e 66 | } 67 | 68 | override fun visit(e: Expr.Let): Expr.Fun? { 69 | return e.enclosingScope?.accept(this) 70 | } 71 | 72 | override fun visit(e: Expr.Let.Rec): Expr.Fun? { 73 | return e.enclosingScope?.accept(this) 74 | } 75 | 76 | override fun visit(e: Expr.If): Expr.Fun? { 77 | return e.enclosingScope?.accept(this) 78 | } 79 | 80 | } -------------------------------------------------------------------------------- /compiler/ckc/src/ck/ast/visitors/ScopeLinkingVisitor.kt: -------------------------------------------------------------------------------- 1 | package ck.ast.visitors 2 | 3 | import ck.ast.node.Expr 4 | import ck.ast.node.ASTNode 5 | import ck.ast.node.CkFile 6 | 7 | //TODO: add enclosingLoop field to break expr and link it up here 8 | class ScopeLinkingVisitor : BaseASTVisitor() { 9 | 10 | //start with null scope (top level) 11 | var currentScope: ASTNode? = null 12 | 13 | override fun visit(e: Expr.Fun.DataPredicate) { 14 | e.enclosingScope = currentScope 15 | } 16 | 17 | override fun visit(e: Expr.Fun.DataAccessor) { 18 | e.enclosingScope = currentScope 19 | } 20 | 21 | override fun visit(e: Expr.Fun.DataConstructor) { 22 | e.enclosingScope = currentScope 23 | } 24 | 25 | override fun visit(f: CkFile) { 26 | currentScope = f 27 | f.expr.accept(this) 28 | } 29 | 30 | //leaf node, do nothing 31 | override fun visit(e: Expr.Tuple) { 32 | e.enclosingScope = currentScope 33 | } 34 | 35 | //not a ref or an enclosing scope, just have to visit children 36 | override fun visit(e: Expr.Sequence) { 37 | e.enclosingScope = currentScope 38 | e.first.accept(this) 39 | e.second.accept(this) 40 | } 41 | 42 | override fun visit(e: Expr.Natural) { 43 | e.enclosingScope = currentScope 44 | } 45 | 46 | override fun visit(e: Expr.Ref) { 47 | e.enclosingScope = currentScope 48 | } 49 | 50 | override fun visit(e: Expr.Apply) { 51 | e.enclosingScope = currentScope 52 | e.fn.accept(this) 53 | e.args.forEach { a -> a.accept(this) } 54 | } 55 | 56 | override fun visit(e: Expr.Unary) { 57 | e.enclosingScope = currentScope 58 | e.operand.accept(this) 59 | } 60 | 61 | override fun visit(e: Expr.Binary) { 62 | e.enclosingScope = currentScope 63 | e.lhs.accept(this) 64 | e.rhs.accept(this) 65 | } 66 | 67 | override fun visit(e: Expr.Cond) { 68 | e.enclosingScope = currentScope 69 | e.cond.accept(this) 70 | e.csq.accept(this) 71 | e.alt.accept(this) 72 | } 73 | 74 | override fun visit(e: Expr.Assign) { 75 | e.enclosingScope = currentScope 76 | e.target.accept(this) 77 | e.value.accept(this) 78 | } 79 | 80 | //ck.ast.node.Expr.Fun creates a new scope 81 | override fun visit(e: Expr.Fun) { 82 | //first save current scope as enclosing scope for e 83 | e.enclosingScope = currentScope 84 | //then set the current scope to e 85 | currentScope = e 86 | //then visit the body of e with the new current scope set 87 | e.body.accept(this) 88 | //then reset enclosing scope 89 | currentScope = e.enclosingScope 90 | } 91 | 92 | override fun visit(e: Expr.CFun) { 93 | e.enclosingScope = currentScope 94 | } 95 | 96 | //ck.ast.node.Expr.Let creates a new scope 97 | override fun visit(e: Expr.Let) { 98 | //visit value of let in currentScope 99 | e.binding.value.accept(this) 100 | //save current scope as enclosing scope for e 101 | e.enclosingScope = currentScope 102 | //then set the current scope to e 103 | currentScope = e 104 | //then visit the body of e with the new current scope set 105 | e.body.accept(this) 106 | //then reset enclosing scope 107 | currentScope = e.enclosingScope 108 | } 109 | 110 | override fun visit(e: Expr.Let.Rec) { 111 | //first save current scope as enclosing scope for e 112 | e.enclosingScope = currentScope 113 | //then set the current scope to e 114 | currentScope = e 115 | //then visit values of let operand 116 | e.bindings.forEach { b -> b.value.accept(this) } 117 | //then visit the body of e with the new current scope set 118 | e.body.accept(this) 119 | //then reset enclosing scope 120 | currentScope = e.enclosingScope 121 | } 122 | 123 | override fun visit(e: Expr.If) { 124 | e.enclosingScope = currentScope 125 | e.cond.accept(this) 126 | e.csq.accept(this) 127 | e.alt?.accept(this) 128 | } 129 | 130 | } -------------------------------------------------------------------------------- /compiler/ckc/src/ck/compiler/StackFrame.kt: -------------------------------------------------------------------------------- 1 | package ck.compiler 2 | 3 | import util.extensions.toDelimitedString 4 | 5 | class StackFrame { 6 | 7 | val locals = ArrayList>() 8 | 9 | fun getLayout(): List { 10 | val ret = ArrayList() 11 | locals.forEachIndexed { index, b -> if (b.second) ret.add(index) } 12 | return ret 13 | } 14 | 15 | fun getLayoutString(): String { 16 | return "[${getLayout().map { i -> i.toString() }.toDelimitedString(", ")}]" 17 | } 18 | 19 | fun push(id: String, isRef: Boolean): Int { 20 | locals.add(Pair(id, isRef)) 21 | return locals.size - 1 22 | } 23 | 24 | fun dup() { 25 | locals.add(locals[locals.size - 1]) 26 | } 27 | 28 | fun lookup(id: String): Int? { 29 | val i = locals.indexOfLast { l -> l.first == id } 30 | return if (i == -1) null else i 31 | } 32 | 33 | fun pop() { 34 | locals.removeAt(locals.size - 1) 35 | } 36 | 37 | fun clear() { 38 | locals.removeAll(locals) 39 | } 40 | 41 | } 42 | 43 | -------------------------------------------------------------------------------- /compiler/ckc/src/ck/grammar/Parse.kt: -------------------------------------------------------------------------------- 1 | package ck.grammar 2 | 3 | import ck.ast.node.CkFile 4 | import ck.ast.node.Expr 5 | import ck.grammar.visitors.ExprVisitor 6 | import ck.grammar.visitors.FileVisitor 7 | import ckLexer 8 | import ckParser 9 | import org.antlr.v4.runtime.CharStream 10 | import org.antlr.v4.runtime.CommonTokenStream 11 | import org.antlr.v4.runtime.misc.ParseCancellationException 12 | import util.antlr.ThrowingErrorListener 13 | import util.either.Either 14 | 15 | sealed class Parse { 16 | 17 | data class Error(val what: String) 18 | 19 | companion object { 20 | 21 | fun getParser(stream: CharStream): ckParser { 22 | val lexer = ckLexer(stream) 23 | val tokens = CommonTokenStream(lexer) 24 | val ckParser = ckParser(tokens) 25 | ckParser.removeErrorListeners() 26 | ckParser.addErrorListener(ThrowingErrorListener.INSTANCE) 27 | return ckParser 28 | } 29 | 30 | fun expr(stream: CharStream): Either { 31 | val parser = getParser(stream) 32 | return try { 33 | val context = parser.expr() 34 | Either.right(context.accept(ExprVisitor())) 35 | } catch (e: ParseCancellationException) { 36 | Either.left(Error(e.localizedMessage)) 37 | } 38 | } 39 | 40 | fun file(stream: CharStream): Either { 41 | val parser = getParser(stream) 42 | return try { 43 | val context = parser.file() 44 | Either.right(context.accept(FileVisitor())) 45 | } catch (e: ParseCancellationException) { 46 | Either.left(Error(e.localizedMessage)) 47 | } 48 | } 49 | 50 | } 51 | 52 | } -------------------------------------------------------------------------------- /compiler/ckc/src/ck/grammar/visitors/DeclVisitor.kt: -------------------------------------------------------------------------------- 1 | package ck.grammar.visitors 2 | 3 | import ck.ast.Type 4 | import ck.ast.node.Expr 5 | import ckBaseVisitor 6 | import ckParser 7 | import java.lang.RuntimeException 8 | 9 | class DeclVisitor(private val rest: Expr): ckBaseVisitor() { 10 | 11 | //visit a top level decl 12 | override fun visitTypeDecl(ctx: ckParser.TypeDeclContext?): Expr { 13 | 14 | //add params to env 15 | val env = ArrayList>() 16 | if (ctx!!.typeParams() != null) { 17 | for (paramNode in ctx.typeParams().ID()) { 18 | env.add(Pair(paramNode.text, Type.newVar())) 19 | } 20 | } 21 | 22 | //check for duplicate params 23 | if (env.distinctBy { p -> p.first }.size != env.size) 24 | throw RuntimeException("type parameters must be unique") 25 | 26 | //create type 27 | //TODO: check that type name is unique in context, maybe not here 28 | val type = Type.Op(ctx.ID().text, env.map { p -> p.second }) 29 | 30 | //add type to env (for recursive types) 31 | env.add(Pair(ctx.ID().text, type)) 32 | 33 | //a list of the new bindings that this decl creates 34 | val newBindings = ArrayList() 35 | 36 | //for each product in the sum 37 | ctx.sum().product().forEachIndexed { index, productContext -> 38 | 39 | //create constructor argument types 40 | val constructorArgTypes = 41 | if (productContext.types() == null) 42 | ArrayList() 43 | else 44 | productContext.types().accept(TypesVisitor(env)) 45 | 46 | //create constructor function type 47 | val constructorType = Type.Op("Fun", constructorArgTypes + type) 48 | 49 | //add the constructor fun 50 | newBindings.add( 51 | Expr.Let.Binding( 52 | productContext.ID().text, 53 | constructorType, 54 | Expr.Fun.DataConstructor( 55 | constructorArgTypes.map { at -> Expr.Fun.Param(Type.newId(), at) }, 56 | index, 57 | constructorType 58 | ) 59 | ) 60 | ) 61 | 62 | //create predicate type 63 | val predicateType = Type.Op("Fun", listOf(type, Type.Op("Int"))) 64 | 65 | //add predicate function 66 | newBindings.add( 67 | Expr.Let.Binding( 68 | "is_${productContext.ID().text}", 69 | predicateType, 70 | Expr.Fun.DataPredicate(index, predicateType) 71 | ) 72 | ) 73 | 74 | //for each argument to this constructor add an accessor fun 75 | constructorArgTypes.forEachIndexed { accessorIndex, accessorRetType -> 76 | //create accessor fun type 77 | val accessorType = Type.Op("Fun", listOf(type, accessorRetType)) 78 | //add accessor 79 | newBindings.add( 80 | Expr.Let.Binding( 81 | "${productContext.ID().text}_$accessorIndex", 82 | accessorType, 83 | Expr.Fun.DataAccessor(accessorIndex, accessorType) 84 | ) 85 | ) 86 | } 87 | } 88 | 89 | //return augmented expr 90 | return newBindings.foldRight(rest) { binding, acc -> Expr.Let(binding, acc, acc.t) } 91 | } 92 | } -------------------------------------------------------------------------------- /compiler/ckc/src/ck/grammar/visitors/ExprVisitor.kt: -------------------------------------------------------------------------------- 1 | package ck.grammar.visitors 2 | 3 | import ck.ast.node.Expr 4 | import ck.ast.Type 5 | import ckBaseVisitor 6 | import ckParser 7 | import java.lang.RuntimeException 8 | 9 | class ExprVisitor : ckBaseVisitor() { 10 | 11 | override fun visitNaturalExpr(ctx: ckParser.NaturalExprContext?): Expr = 12 | Expr.Natural(ctx!!.text.toLong()) 13 | 14 | override fun visitSequenceExpr(ctx: ckParser.SequenceExprContext?): Expr = 15 | SequenceVisitor().visit(ctx!!.sequence()) 16 | 17 | //if visiting a let expr by itself then it has no "body" just return value 18 | override fun visitLetExpr(ctx: ckParser.LetExprContext?): Expr = 19 | ctx!!.binding().expr().accept(ExprVisitor()) 20 | 21 | override fun visitLetRecExpr(ctx: ckParser.LetRecExprContext?): Expr { 22 | throw RuntimeException("let rec without body") 23 | } 24 | 25 | // override fun visitTupleExpr(ctx: ckParser.TupleExprContext?): Expr { 26 | // return Expr.Tuple(if (ctx!!.exprs() == null) ArrayList() else ctx.exprs().accept(ExprsVisitor())) 27 | // } 28 | 29 | override fun visitRefExpr(ctx: ckParser.RefExprContext?): Expr = 30 | Expr.Ref(ctx!!.text, Type.newVar()) 31 | 32 | override fun visitApplyExpr(ctx: ckParser.ApplyExprContext?): Expr = 33 | Expr.Apply( 34 | fn = ExprVisitor().visit(ctx!!.expr()), 35 | args = 36 | if (ctx.exprs() != null) ExprsVisitor().visit(ctx.exprs()) 37 | else ArrayList(), 38 | t = Type.newVar() 39 | ) 40 | 41 | override fun visitUnaryExpr(ctx: ckParser.UnaryExprContext?): Expr = 42 | Expr.Unary( 43 | operator = ctx!!.op.text, 44 | operand = ExprVisitor().visit(ctx.expr()), 45 | t = Type.newVar() 46 | ) 47 | 48 | override fun visitMultExpr(ctx: ckParser.MultExprContext?): Expr = 49 | Expr.Binary( 50 | lhs = ExprVisitor().visit(ctx!!.lhs), 51 | operator = ctx.op.text, 52 | rhs = ExprVisitor().visit(ctx.rhs), 53 | t = Type.newVar() 54 | ) 55 | 56 | override fun visitAddExpr(ctx: ckParser.AddExprContext?): Expr = 57 | Expr.Binary( 58 | lhs = ExprVisitor().visit(ctx!!.lhs), 59 | operator = ctx.op.text, 60 | rhs = ExprVisitor().visit(ctx.rhs), 61 | t = Type.newVar() 62 | ) 63 | 64 | override fun visitShiftExpr(ctx: ckParser.ShiftExprContext?): Expr = 65 | Expr.Binary( 66 | lhs = ExprVisitor().visit(ctx!!.lhs), 67 | operator = ctx.op.text, 68 | rhs = ExprVisitor().visit(ctx.rhs), 69 | t = Type.newVar() 70 | ) 71 | 72 | override fun visitRelExpr(ctx: ckParser.RelExprContext?): Expr = 73 | Expr.Binary( 74 | lhs = ExprVisitor().visit(ctx!!.lhs), 75 | operator = ctx.op.text, 76 | rhs = ExprVisitor().visit(ctx.rhs), 77 | t = Type.newVar() 78 | ) 79 | 80 | override fun visitEqualityExpr(ctx: ckParser.EqualityExprContext?): Expr = 81 | Expr.Binary( 82 | lhs = ExprVisitor().visit(ctx!!.lhs), 83 | operator = ctx.op.text, 84 | rhs = ExprVisitor().visit(ctx.rhs), 85 | t = Type.newVar() 86 | ) 87 | 88 | override fun visitBitAndExpr(ctx: ckParser.BitAndExprContext?): Expr = 89 | Expr.Binary( 90 | lhs = ExprVisitor().visit(ctx!!.lhs), 91 | operator = "&", 92 | rhs = ExprVisitor().visit(ctx.rhs), 93 | t = Type.newVar() 94 | ) 95 | 96 | override fun visitBitXorExpr(ctx: ckParser.BitXorExprContext?): Expr = 97 | Expr.Binary( 98 | lhs = ExprVisitor().visit(ctx!!.lhs), 99 | operator = "^", 100 | rhs = ExprVisitor().visit(ctx.rhs), 101 | t = Type.newVar() 102 | ) 103 | 104 | override fun visitBitOrExpr(ctx: ckParser.BitOrExprContext?): Expr = 105 | Expr.Binary( 106 | lhs = ExprVisitor().visit(ctx!!.lhs), 107 | operator = "|", 108 | rhs = ExprVisitor().visit(ctx.rhs), 109 | t = Type.newVar() 110 | ) 111 | 112 | override fun visitAndExpr(ctx: ckParser.AndExprContext?): Expr = 113 | Expr.Binary( 114 | lhs = ExprVisitor().visit(ctx!!.lhs), 115 | operator = "&&", 116 | rhs = ExprVisitor().visit(ctx.rhs), 117 | t = Type.newVar() 118 | ) 119 | 120 | override fun visitOrExpr(ctx: ckParser.OrExprContext?): Expr = 121 | Expr.Binary( 122 | lhs = ExprVisitor().visit(ctx!!.lhs), 123 | operator = "||", 124 | rhs = ExprVisitor().visit(ctx.rhs), 125 | t = Type.newVar() 126 | ) 127 | 128 | override fun visitCondExpr(ctx: ckParser.CondExprContext?): Expr = 129 | Expr.Cond( 130 | cond = ExprVisitor().visit(ctx!!.cond), 131 | csq = ExprVisitor().visit(ctx.con), 132 | alt = ExprVisitor().visit(ctx.alt), 133 | t = Type.newVar() 134 | ) 135 | 136 | override fun visitAssignExpr(ctx: ckParser.AssignExprContext?): Expr = 137 | Expr.Assign( 138 | target = ExprVisitor().visit(ctx!!.target), 139 | value = ExprVisitor().visit(ctx.value), 140 | t = Type.newVar() 141 | ) 142 | 143 | override fun visitCFunExpr(ctx: ckParser.CFunExprContext?): Expr = 144 | Expr.CFun( 145 | ctx!!.ID().text, 146 | ctx.type().accept(TypeVisitor()), 147 | t = Type.newVar() 148 | ) 149 | 150 | override fun visitFunExpr(ctx: ckParser.FunExprContext?): Expr { 151 | return Expr.Fun( 152 | params = 153 | if (ctx!!.params() != null) ctx.params().accept(ParamsVisitor()) 154 | else ArrayList(), 155 | body = ExprVisitor().visit(ctx.expr()), 156 | t = Type.newVar() 157 | ) 158 | } 159 | 160 | override fun visitIfExpr(ctx: ckParser.IfExprContext?): Expr = 161 | Expr.If( 162 | cond = ExprVisitor().visit(ctx!!.cond), 163 | csq = ExprVisitor().visit(ctx.csq), 164 | alt = 165 | if (ctx.alt != null) ExprVisitor().visit(ctx.alt) 166 | else null, 167 | t = Type.newVar() 168 | ) 169 | 170 | } 171 | 172 | //TODO: for some reason I can't put these classes in their own files... 173 | class ParamsVisitor : ckBaseVisitor>() { 174 | override fun visitParams(ctx: ckParser.ParamsContext?): List = 175 | ctx!!.param().map { p -> ParamVisitor().visit(p) } 176 | } 177 | 178 | class ParamVisitor : ckBaseVisitor() { 179 | override fun visitParam(ctx: ckParser.ParamContext?): Expr.Fun.Param = 180 | Expr.Fun.Param( 181 | id = ctx!!.ID().text, 182 | t = Type.newVar() 183 | ) 184 | } 185 | 186 | -------------------------------------------------------------------------------- /compiler/ckc/src/ck/grammar/visitors/ExprsVisitor.kt: -------------------------------------------------------------------------------- 1 | package ck.grammar.visitors 2 | 3 | import ck.ast.node.Expr 4 | import ckBaseVisitor 5 | import ckParser 6 | 7 | class ExprsVisitor : ckBaseVisitor>() { 8 | override fun visitExprs(ctx: ckParser.ExprsContext?): List = 9 | ctx!!.expr().map { ectx -> ExprVisitor().visit(ectx) } 10 | } -------------------------------------------------------------------------------- /compiler/ckc/src/ck/grammar/visitors/FileVisitor.kt: -------------------------------------------------------------------------------- 1 | package ck.grammar.visitors 2 | 3 | import ck.ast.node.CkFile 4 | import ck.ast.node.Decl 5 | import ck.ast.node.Expr 6 | import ckBaseVisitor 7 | import ckParser 8 | 9 | //ck File visitor 10 | 11 | class FileVisitor : ckBaseVisitor() { 12 | override fun visitFile(ctx: ckParser.FileContext?): CkFile { 13 | val expr = 14 | if (ctx!!.expr() != null) 15 | ExprVisitor().visit(ctx.expr()) 16 | else 17 | Expr.Tuple() 18 | return CkFile(emptyList(), ctx.decl().foldRight(expr) { declContext, acc -> declContext.accept(DeclVisitor(acc)) }) 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /compiler/ckc/src/ck/grammar/visitors/SequenceVisitor.kt: -------------------------------------------------------------------------------- 1 | package ck.grammar.visitors 2 | 3 | import ck.ast.node.Expr 4 | import ck.ast.Type 5 | import ckBaseVisitor 6 | import ckParser 7 | 8 | class SequenceVisitor : ckBaseVisitor() { 9 | override fun visitSequence(ctx: ckParser.SequenceContext?): Expr { 10 | val expr = ctx!!.expr() 11 | return if (ctx.sequence() == null) 12 | //if sequence is null then return expr 13 | expr.accept(ExprVisitor()) 14 | else 15 | when (expr) { 16 | is ckParser.LetRecExprContext -> 17 | Expr.Let.Rec( 18 | expr.binding().map { b -> 19 | Expr.Let.Binding( 20 | b.ID().text, 21 | if (b.type() == null) null else b.type().accept(TypeVisitor()), 22 | b.expr().accept(ExprVisitor()) 23 | ) 24 | }, 25 | ctx.sequence().accept(SequenceVisitor()), 26 | Type.newVar() 27 | ) 28 | is ckParser.LetExprContext -> 29 | //if expr is let then make sequence it's body 30 | Expr.Let( 31 | Expr.Let.Binding( 32 | expr.binding().ID().text, 33 | if (expr.binding().type() == null) null else expr.binding().type().accept(TypeVisitor()), 34 | ExprVisitor().visit(expr.binding().expr()) 35 | ), 36 | SequenceVisitor().visit(ctx.sequence()), 37 | Type.newVar() 38 | ) 39 | else -> 40 | //otherwise it's a normal sequence 41 | Expr.Sequence( 42 | first = ExprVisitor().visit(ctx.expr()), 43 | second = SequenceVisitor().visit(ctx.sequence()), 44 | t = Type.newVar() 45 | ) 46 | } 47 | } 48 | } -------------------------------------------------------------------------------- /compiler/ckc/src/ck/grammar/visitors/TypeVisitor.kt: -------------------------------------------------------------------------------- 1 | package ck.grammar.visitors 2 | 3 | import ck.ast.Type 4 | import ckBaseVisitor 5 | import ckParser 6 | import java.lang.RuntimeException 7 | 8 | class TypeVisitor(val env: List> = emptyList()) : ckBaseVisitor() { 9 | 10 | override fun visitCtorType(ctx: ckParser.CtorTypeContext?): Type { 11 | return Type.Op(ctx!!.ID().text, ctx.types().accept(TypesVisitor(env))) 12 | } 13 | 14 | override fun visitSimpleType(ctx: ckParser.SimpleTypeContext?): Type { 15 | val found = env.find { p -> p.first == ctx!!.ID().text } 16 | return when { 17 | found != null -> found.second 18 | ctx!!.ID().text == "Int" -> Type.Op("Int", emptyList()) 19 | ctx.ID().text == "Unit" -> Type.Op("Unit", emptyList()) 20 | else -> throw RuntimeException("unknown type ${ctx.ID().text}") 21 | } 22 | } 23 | 24 | override fun visitFunType(ctx: ckParser.FunTypeContext?): Type = 25 | Type.Op( 26 | "Fun", 27 | (if (ctx!!.types() != null) TypesVisitor(env).visit(ctx.types()) 28 | else emptyList()) 29 | + this.visit(ctx.type()) 30 | ) 31 | } -------------------------------------------------------------------------------- /compiler/ckc/src/ck/grammar/visitors/TypesVisitor.kt: -------------------------------------------------------------------------------- 1 | package ck.grammar.visitors 2 | 3 | import ck.ast.Type 4 | import ckBaseVisitor 5 | import ckParser 6 | 7 | class TypesVisitor(val env: List> = emptyList()) : ckBaseVisitor>() { 8 | override fun visitTypes(ctx: ckParser.TypesContext?): List = 9 | ctx!!.type().map { t -> TypeVisitor(env).visit(t) } 10 | } -------------------------------------------------------------------------------- /compiler/ckc/test/AnalyzeTest.kt: -------------------------------------------------------------------------------- 1 | import ck.analyze.Analyze 2 | import ck.ast.Type 3 | import ck.grammar.Parse 4 | import org.antlr.v4.runtime.CharStreams 5 | import org.junit.jupiter.api.Assertions.* 6 | import org.junit.jupiter.api.Test 7 | 8 | internal class AnalyzeTest { 9 | 10 | companion object { 11 | fun getType(input: String): Type { 12 | val expr = Parse.expr(CharStreams.fromString(input)).right()!! 13 | Analyze.analyze(expr, null, null) 14 | return Analyze.prune(expr.t) 15 | } 16 | } 17 | 18 | @Test 19 | fun test() { 20 | assertEquals(getType("()"), Type.Op("Unit")) 21 | assertEquals(getType("{let a = 42; a}"), Type.Op("Int")) 22 | assertEquals(getType("{let id = (a): a; id(42)}"), Type.Op("Int")) 23 | } 24 | } -------------------------------------------------------------------------------- /compiler/ckc/test/CompilationVisitorTest.kt: -------------------------------------------------------------------------------- 1 | import ck.ast.visitors.CompilationVisitor 2 | import ck.ast.visitors.ComputeCapturesVisitor 3 | import ck.ast.visitors.ScopeLinkingVisitor 4 | import ck.grammar.Parse 5 | import org.antlr.v4.runtime.CharStreams 6 | import org.junit.jupiter.api.Assertions.* 7 | import org.junit.jupiter.api.Test 8 | 9 | internal class CompilationVisitorTest { 10 | @Test 11 | fun testNaturalExpr() { 12 | val visitor = CompilationVisitor() 13 | val expr = Parse.expr(CharStreams.fromString("42")).right()!! 14 | expr.accept(visitor) 15 | assert(visitor.frame.locals.size == 1) 16 | } 17 | @Test 18 | fun testBinExpr() { 19 | var visitor = CompilationVisitor() 20 | var expr = Parse.expr(CharStreams.fromString("43 < 42")).right()!! 21 | expr.accept(visitor) 22 | assert(visitor.frame.locals.size == 1) 23 | 24 | visitor = CompilationVisitor() 25 | expr = Parse.expr(CharStreams.fromString("43 && 42")).right()!! 26 | expr.accept(visitor) 27 | assert(visitor.frame.locals.size == 1) 28 | 29 | visitor = CompilationVisitor() 30 | expr = Parse.expr(CharStreams.fromString("43 || 42")).right()!! 31 | expr.accept(visitor) 32 | assert(visitor.frame.locals.size == 1) 33 | } 34 | @Test 35 | fun testSequenceExpr() { 36 | val visitor = CompilationVisitor() 37 | val expr = Parse.expr(CharStreams.fromString("{42; 43}")).right()!! 38 | expr.accept(visitor) 39 | assert(visitor.frame.locals.size == 1) 40 | } 41 | @Test 42 | fun testLetExpr() { 43 | var visitor = CompilationVisitor() 44 | var expr = Parse.expr(CharStreams.fromString("{let a = 42; a}")).right()!! 45 | expr.accept(ScopeLinkingVisitor()) 46 | expr.accept(visitor) 47 | assert(visitor.frame.locals.size == 1) 48 | expr = Parse.expr(CharStreams.fromString("{\n" + 49 | " let read = cfun native_read ():Int;\n" + 50 | " let write = cfun native_write (Int):Unit;\n" + 51 | " \n" + 52 | " let left = (a): (l, r): l(a);\n" + 53 | " let right = (b): (l, r): r(b);\n" + 54 | " let map = (e, l, r): e(l, r);\n" + 55 | " \n" + 56 | " let char = read();\n" + 57 | " \n" + 58 | " let either = \n" + 59 | " if (char < 97)\n" + 60 | " left(():60)\n" + 61 | " else\n" + 62 | " right(62);\n" + 63 | " \n" + 64 | " map(either, (f): write(f()), (i): write(i));\n" + 65 | " //write(map(either, (f): f(), (i): i));\n" + 66 | " \n" + 67 | " let cons = (a, b): (s): s(a, b);\n" + 68 | " let fst = (p): p((a,b): a);\n" + 69 | " let snd = (p): p((a,b): b);\n" + 70 | " \n" + 71 | " let pair = cons((): 60, cons(62, ()));\n" + 72 | " \n" + 73 | " write(fst(pair)());\n" + 74 | " write(fst(snd(pair)))\n" + 75 | "}")).right()!! 76 | visitor = CompilationVisitor() 77 | expr.accept(ScopeLinkingVisitor()) 78 | expr.accept(visitor) 79 | assert(visitor.frame.locals.size == 1) 80 | } 81 | @Test 82 | fun testIfExpr() { 83 | val visitor = CompilationVisitor() 84 | val expr = Parse.expr(CharStreams.fromString("if (1) 42 else 43")).right()!! 85 | expr.accept(ScopeLinkingVisitor()) 86 | expr.accept(visitor) 87 | assert(visitor.frame.locals.size == 1) 88 | } 89 | @Test 90 | fun testFunExpr() { 91 | val visitor = CompilationVisitor() 92 | val expr = Parse.expr(CharStreams.fromString("(a): a")).right()!! 93 | expr.accept(ScopeLinkingVisitor()) 94 | expr.accept(visitor) 95 | assert(visitor.frame.locals.size == 1) 96 | } 97 | @Test 98 | fun testApplyExpr() { 99 | var visitor = CompilationVisitor() 100 | var expr = Parse.expr(CharStreams.fromString("{(a): a}(42)")).right()!! 101 | expr.accept(ScopeLinkingVisitor()) 102 | expr.accept(visitor) 103 | assert(visitor.frame.locals.size == 1) 104 | 105 | visitor = CompilationVisitor() 106 | expr = Parse.expr(CharStreams.fromString("let id = (a): a; id(42)")).right()!! 107 | expr.accept(ScopeLinkingVisitor()) 108 | expr.accept(visitor) 109 | assert(visitor.frame.locals.size == 1) 110 | } 111 | } -------------------------------------------------------------------------------- /compiler/ckc/test/ParseTest.kt: -------------------------------------------------------------------------------- 1 | import ck.ast.Type 2 | import ck.ast.node.Expr 3 | import ck.grammar.Parse 4 | import org.antlr.v4.runtime.CharStreams 5 | import org.junit.jupiter.api.Test 6 | 7 | import org.junit.jupiter.api.Assertions.* 8 | 9 | internal class ParseTest { 10 | 11 | @Test 12 | fun expr() { 13 | 14 | var input = "a" 15 | var expr = Parse.expr(CharStreams.fromString(input)) 16 | assertEquals(expr.right()!!, Expr.Ref("a", Type.newVar())) 17 | 18 | input = "Oops" 19 | expr = Parse.expr(CharStreams.fromString(input)) 20 | assertTrue(expr.isLeft()) 21 | 22 | input = "(a): a" 23 | expr = Parse.expr(CharStreams.fromString(input)) 24 | assertEquals( 25 | expr.right()!!, 26 | Expr.Fun( 27 | listOf(Expr.Fun.Param("a", Type.newVar())), 28 | Expr.Ref("a", Type.newVar()), 29 | Type.newVar() 30 | ) 31 | ) 32 | 33 | input = "(oops)-> a" 34 | expr = Parse.expr(CharStreams.fromString(input)) 35 | assertTrue(expr.isLeft()) 36 | } 37 | 38 | @Test 39 | fun file() { 40 | 41 | } 42 | 43 | } -------------------------------------------------------------------------------- /compiler/compiler.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /compiler/lib/antlr4-runtime-4.7.2.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/clnhlzmn/CopperKitten/eee91947d8011576ec30a1934c829f651c911505/compiler/lib/antlr4-runtime-4.7.2.jar -------------------------------------------------------------------------------- /compiler/lib/apiguardian-api-1.0.0.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/clnhlzmn/CopperKitten/eee91947d8011576ec30a1934c829f651c911505/compiler/lib/apiguardian-api-1.0.0.jar -------------------------------------------------------------------------------- /compiler/lib/commons-cli-1.4.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/clnhlzmn/CopperKitten/eee91947d8011576ec30a1934c829f651c911505/compiler/lib/commons-cli-1.4.jar -------------------------------------------------------------------------------- /compiler/lib/hamcrest-all-1.3.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/clnhlzmn/CopperKitten/eee91947d8011576ec30a1934c829f651c911505/compiler/lib/hamcrest-all-1.3.jar -------------------------------------------------------------------------------- /compiler/lib/junit-4.13-beta-2.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/clnhlzmn/CopperKitten/eee91947d8011576ec30a1934c829f651c911505/compiler/lib/junit-4.13-beta-2.jar -------------------------------------------------------------------------------- /compiler/lib/junit-jupiter-api-5.4.1.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/clnhlzmn/CopperKitten/eee91947d8011576ec30a1934c829f651c911505/compiler/lib/junit-jupiter-api-5.4.1.jar -------------------------------------------------------------------------------- /compiler/lib/junit-jupiter-api-5.5.0-M1.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/clnhlzmn/CopperKitten/eee91947d8011576ec30a1934c829f651c911505/compiler/lib/junit-jupiter-api-5.5.0-M1.jar -------------------------------------------------------------------------------- /compiler/lib/junit-platform-commons-1.4.1.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/clnhlzmn/CopperKitten/eee91947d8011576ec30a1934c829f651c911505/compiler/lib/junit-platform-commons-1.4.1.jar -------------------------------------------------------------------------------- /compiler/lib/junit-platform-commons-1.5.0-M1.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/clnhlzmn/CopperKitten/eee91947d8011576ec30a1934c829f651c911505/compiler/lib/junit-platform-commons-1.5.0-M1.jar -------------------------------------------------------------------------------- /compiler/lib/kotlin-reflect-sources.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/clnhlzmn/CopperKitten/eee91947d8011576ec30a1934c829f651c911505/compiler/lib/kotlin-reflect-sources.jar -------------------------------------------------------------------------------- /compiler/lib/kotlin-reflect.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/clnhlzmn/CopperKitten/eee91947d8011576ec30a1934c829f651c911505/compiler/lib/kotlin-reflect.jar -------------------------------------------------------------------------------- /compiler/lib/kotlin-stdlib-jdk7-sources.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/clnhlzmn/CopperKitten/eee91947d8011576ec30a1934c829f651c911505/compiler/lib/kotlin-stdlib-jdk7-sources.jar -------------------------------------------------------------------------------- /compiler/lib/kotlin-stdlib-jdk7.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/clnhlzmn/CopperKitten/eee91947d8011576ec30a1934c829f651c911505/compiler/lib/kotlin-stdlib-jdk7.jar -------------------------------------------------------------------------------- /compiler/lib/kotlin-stdlib-jdk8-sources.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/clnhlzmn/CopperKitten/eee91947d8011576ec30a1934c829f651c911505/compiler/lib/kotlin-stdlib-jdk8-sources.jar -------------------------------------------------------------------------------- /compiler/lib/kotlin-stdlib-jdk8.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/clnhlzmn/CopperKitten/eee91947d8011576ec30a1934c829f651c911505/compiler/lib/kotlin-stdlib-jdk8.jar -------------------------------------------------------------------------------- /compiler/lib/kotlin-stdlib-sources.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/clnhlzmn/CopperKitten/eee91947d8011576ec30a1934c829f651c911505/compiler/lib/kotlin-stdlib-sources.jar -------------------------------------------------------------------------------- /compiler/lib/kotlin-stdlib.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/clnhlzmn/CopperKitten/eee91947d8011576ec30a1934c829f651c911505/compiler/lib/kotlin-stdlib.jar -------------------------------------------------------------------------------- /compiler/lib/kotlin-test-sources.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/clnhlzmn/CopperKitten/eee91947d8011576ec30a1934c829f651c911505/compiler/lib/kotlin-test-sources.jar -------------------------------------------------------------------------------- /compiler/lib/kotlin-test.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/clnhlzmn/CopperKitten/eee91947d8011576ec30a1934c829f651c911505/compiler/lib/kotlin-test.jar -------------------------------------------------------------------------------- /compiler/lib/opentest4j-1.1.1.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/clnhlzmn/CopperKitten/eee91947d8011576ec30a1934c829f651c911505/compiler/lib/opentest4j-1.1.1.jar -------------------------------------------------------------------------------- /compiler/out/artifacts/cka_jar/cka.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/clnhlzmn/CopperKitten/eee91947d8011576ec30a1934c829f651c911505/compiler/out/artifacts/cka_jar/cka.jar -------------------------------------------------------------------------------- /compiler/out/artifacts/ckc_jar/ckc.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/clnhlzmn/CopperKitten/eee91947d8011576ec30a1934c829f651c911505/compiler/out/artifacts/ckc_jar/ckc.jar -------------------------------------------------------------------------------- /compiler/util/src/util/antlr/ThrowingErrorListener.kt: -------------------------------------------------------------------------------- 1 | package util.antlr 2 | 3 | import org.antlr.v4.runtime.BaseErrorListener 4 | import org.antlr.v4.runtime.RecognitionException 5 | import org.antlr.v4.runtime.Recognizer 6 | import org.antlr.v4.runtime.misc.ParseCancellationException 7 | 8 | class ThrowingErrorListener : BaseErrorListener() { 9 | 10 | @Throws(ParseCancellationException::class) 11 | override fun syntaxError( 12 | recognizer: Recognizer<*, *>?, 13 | offendingSymbol: Any?, 14 | line: Int, 15 | charPositionInLine: Int, 16 | msg: String?, 17 | e: RecognitionException? 18 | ) { 19 | throw ParseCancellationException("line $line:$charPositionInLine $msg") 20 | } 21 | 22 | companion object { 23 | 24 | val INSTANCE = ThrowingErrorListener() 25 | } 26 | } -------------------------------------------------------------------------------- /compiler/util/src/util/either/Either.kt: -------------------------------------------------------------------------------- 1 | package util.either 2 | 3 | sealed class Either { 4 | 5 | abstract fun left(): A? 6 | abstract fun right(): B? 7 | 8 | abstract fun isLeft(): Boolean 9 | abstract fun isRight(): Boolean 10 | 11 | abstract fun mapLeft(f: (A) -> C): Either 12 | abstract fun mapRight(f: (B) -> C): Either 13 | abstract fun map(l: (A) -> C, r: (B) -> D): Either 14 | 15 | infix fun compose(rhs: Either): Either> { 16 | return when { 17 | isLeft() -> Either.left(left()!!) 18 | rhs.isLeft() -> Either.left(rhs.left()!!) 19 | else -> Either.right(Pair(right()!!, rhs.right()!!)) 20 | } 21 | } 22 | 23 | data class Left(val left: A) : Either() { 24 | override fun left(): A? = left 25 | override fun right(): B? = null 26 | override fun isLeft(): Boolean = true 27 | override fun isRight(): Boolean = false 28 | override fun mapLeft(f: (A) -> C): Either = Left(f(left)) 29 | override fun mapRight(f: (B) -> C): Either = Left(left) 30 | override fun map(l: (A) -> C, r: (B) -> D): Either = Left(l(left)) 31 | } 32 | 33 | data class Right(val right: B) : Either() { 34 | override fun left(): A? = null 35 | override fun right(): B? = right 36 | override fun isLeft(): Boolean = false 37 | override fun isRight(): Boolean = true 38 | override fun mapLeft(f: (A) -> C): Either = Right(right) 39 | override fun mapRight(f: (B) -> C): Either = Right(f(right)) 40 | override fun map(l: (A) -> C, r: (B) -> D): Either = Right(r(right)) 41 | } 42 | 43 | companion object { 44 | fun left(l: A): Either = Left(l) 45 | fun right(r: B): Either = Right(r) 46 | } 47 | 48 | } 49 | 50 | fun Collection>.foldRightEither(l: (A) -> A, r: (List) -> B): Either { 51 | val acc = arrayListOf() 52 | for (item in this) 53 | if (item.isRight()) 54 | acc.add(item.right()!!) 55 | else 56 | return Either.left(l(item.left()!!)) 57 | return Either.right(r(acc)) 58 | } 59 | 60 | fun Collection>.foldLeftEither(l: (List) -> A, r: (B) -> B): Either { 61 | val acc = arrayListOf() 62 | for (item in this) 63 | if (item.isLeft()) 64 | acc.add(item.left()!!) 65 | else 66 | return Either.right(r(item.right()!!)) 67 | return Either.left(l(acc)) 68 | } 69 | 70 | -------------------------------------------------------------------------------- /compiler/util/src/util/extensions/Extensions.kt: -------------------------------------------------------------------------------- 1 | package util.extensions 2 | 3 | //create a string from list elements with a separator 4 | fun List.toDelimitedString(delimiter: String): String = 5 | if (isEmpty()) "" 6 | else map { i -> i.toString() }.reduce { acc, s -> "$acc$delimiter$s" } 7 | 8 | data class Error(val what: String) -------------------------------------------------------------------------------- /compiler/util/test/util/either/EitherTest.kt: -------------------------------------------------------------------------------- 1 | import org.junit.jupiter.api.Assertions.* 2 | import org.junit.jupiter.api.Test 3 | import util.either.Either 4 | import util.either.foldRightEither 5 | 6 | internal class EitherTest { 7 | 8 | @Test 9 | fun eitherTest() { 10 | 11 | var either = Either.left("oops") 12 | assertEquals(either.left()!!, "oops") 13 | assertEquals(either.right(), null) 14 | 15 | assertEquals(either.map({l -> l.toUpperCase()}, { r -> r * 2}).left()!!, "OOPS") 16 | assertEquals(either.map({l -> l.toUpperCase()}, { r -> r * 2}).right(), null) 17 | 18 | either = Either.right(42) 19 | assertEquals(either.right()!!, 42) 20 | assertEquals(either.left(), null) 21 | 22 | assertEquals(either.map({l -> l.toUpperCase()}, { r -> r * 2}).right()!!, 84) 23 | assertEquals(either.map({l -> l.toUpperCase()}, { r -> r * 2}).left(), null) 24 | 25 | var items = listOf>(Either.right(42), Either.right(2), Either.left("oops")) 26 | var res = items.foldRightEither( 27 | { "error" }, 28 | { r -> r[0] + r[1] } 29 | ) 30 | assertEquals(res.left()!!, "error") 31 | 32 | items = listOf(Either.right(42), Either.right(2), Either.right(3)) 33 | res = items.foldRightEither( 34 | { "error" }, 35 | { (a, b, c) -> a + b + c } 36 | ) 37 | assertEquals(res.right()!!, 47) 38 | 39 | (Either.right(42) 40 | compose Either.right("42")) 41 | .map ( 42 | { assertFalse(true) }, 43 | { (i, s) -> 44 | assertEquals(i, 42) 45 | assertEquals(s, "42") 46 | } 47 | ) 48 | 49 | (Either.right(42) 50 | compose Either.right("42") 51 | compose Either.right(84)) 52 | .map ( 53 | { assertFalse(true) }, 54 | { (f, l) -> 55 | val (i, s) = f 56 | assertEquals(i, 42) 57 | assertEquals(s, "42") 58 | assertEquals(l, 84) 59 | } 60 | ) 61 | 62 | (Either.right(42) 63 | compose Either.left("oops") 64 | compose Either.right(84)) 65 | .map ( 66 | { assertEquals(it, "oops") }, 67 | { (f, l) -> 68 | val (i, s) = f 69 | assertEquals(i, 42) 70 | assertEquals(s, "42") 71 | assertEquals(l, 84) 72 | } 73 | ) 74 | 75 | 76 | } 77 | 78 | } -------------------------------------------------------------------------------- /compiler/util/util.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /example/ADT.ck: -------------------------------------------------------------------------------- 1 | 2 | type List = (A) nil() | cons(A, List(A)) 3 | 4 | { 5 | let rec len = (l) 6 | if (is_nil(l)) 7 | 0 8 | else 9 | 1 + len(cons_1(l)); 10 | let myList = cons(1, cons(2, cons(3, nil()))); 11 | len(myList) 12 | } -------------------------------------------------------------------------------- /example/cons.ck: -------------------------------------------------------------------------------- 1 | { 2 | let cons = (a, b) (s) s(a, b); 3 | let fst = (p) p((a,b) a); 4 | let snd = (p) p((a,b) b); 5 | fst(cons(2, 3)); 6 | fst(cons(() 2, 3)) 7 | } -------------------------------------------------------------------------------- /example/either.ck: -------------------------------------------------------------------------------- 1 | 2 | 3 | //modules not currently implemented 4 | module Either = { 5 | 6 | type T = (A, B) left(A) | right(B) 7 | 8 | let map = (e, l, r) 9 | if (is_left(e)) 10 | l(left_0(e)) 11 | else 12 | r(right_0(e)) 13 | 14 | } 15 | 16 | -------------------------------------------------------------------------------- /example/even.ck: -------------------------------------------------------------------------------- 1 | { 2 | let rec even = (n) if (n == 0) 1 else odd(n - 1) 3 | and odd = (n) if (n == 1) 1 else even(n - 1); 4 | even(42) 5 | } -------------------------------------------------------------------------------- /example/fact.ck: -------------------------------------------------------------------------------- 1 | { 2 | let write = cfun native_write (Int)Unit; 3 | let rec fact = (n) if (n < 2) 1 else n * fact(n - 1); 4 | write(fact(3)) 5 | } -------------------------------------------------------------------------------- /example/howToCompileModules.txt: -------------------------------------------------------------------------------- 1 | 2 | 3 | module Foo = { 4 | let a = 42 5 | } 6 | 7 | print(Foo.a) 8 | 9 | //becomes 10 | 11 | { let `Foo.a` = 42; 12 | print(`Foo.a`) } 13 | 14 | -------------------------------------------------------------------------------- /example/id.ck: -------------------------------------------------------------------------------- 1 | { 2 | let id = (a) a; 3 | id (42) 4 | } -------------------------------------------------------------------------------- /example/id2.ck: -------------------------------------------------------------------------------- 1 | 2 | { 3 | let id = (a) a; 4 | let id2 = id; 5 | let foo = (a) id(a); 6 | id2(42); 7 | id2(() 42); 8 | foo(42); 9 | {(a) id(a)}(42) 10 | } -------------------------------------------------------------------------------- /example/simple.ck: -------------------------------------------------------------------------------- 1 | 2 | { 3 | let foo = cfun foo (Int)Int; 4 | foo(42) 5 | } -------------------------------------------------------------------------------- /example/simple/makefile: -------------------------------------------------------------------------------- 1 | 2 | #ck compiler and ck assembler executables 3 | CKC = java -jar ../../compiler/out/artifacts/ckc_jar/ckc.jar 4 | CKA = java -jar ../../compiler/out/artifacts/cka_jar/cka.jar 5 | 6 | #ck assembler options 7 | STACKSIZE = 1000 8 | HEAPSIZE = 10000 9 | #set WORDSIZE for target machine 10 | WORDSIZE = 8 11 | GC = copying 12 | #DEBUG = -d 13 | DEBUG = 14 | 15 | CKFLAGS = ${DEBUG} 16 | 17 | #cka options 18 | CKAFLAGS = -s ${STACKSIZE} -m ${HEAPSIZE} -w ${WORDSIZE} -g ${GC} 19 | 20 | #C flags 21 | CFLAGS = -Wall -Wextra 22 | 23 | #path to ck runtime implementation 24 | RUNTIMEDIR = ../../runtime 25 | 26 | #chosen gc impl 27 | GCIMPL = ../../runtime/${GC}_gc.c 28 | 29 | #directory of output 30 | OUTDIR = out 31 | 32 | #make outdir and simple_io.exe 33 | all: ${OUTDIR} ${OUTDIR}/simple_io 34 | 35 | out: 36 | mkdir out 37 | 38 | #use gcc to compile generated c code 39 | out/simple_io: out/simple_io.c 40 | gcc out/simple_io.c ${RUNTIMEDIR}/builtin_cfuns.c ${GCIMPL} -o ${OUTDIR}/simple_io -I${RUNTIMEDIR} ${CFLAGS} 41 | 42 | #use cka to generate c from simple_io.cka 43 | out/simple_io.c: out/simple_io.cka 44 | ${CKA} -i out/simple_io.cka -o ${OUTDIR}/simple_io.c ${CKAFLAGS} 45 | 46 | #use ckc to generate cka from simple_io.ck 47 | out/simple_io.cka: simple_io.ck 48 | ${CKC} -i simple_io.ck -o ${OUTDIR}/simple_io.cka ${CKFLAGS} 49 | 50 | #remove outdir 51 | clean: 52 | rm -rf ${OUTDIR} -------------------------------------------------------------------------------- /example/simple/simple_io.ck: -------------------------------------------------------------------------------- 1 | 2 | 3 | type List = (A) nil() | cons(A, List(A)) 4 | 5 | type Either = (A, B) left(A) | right(B) 6 | 7 | { 8 | //native read and write funs for chars 9 | let read = cfun native_read ()Int; 10 | let write = cfun native_write (Int)Unit; 11 | 12 | //read a char 13 | let char = read(); 14 | 15 | //either: Either(()Int, Int) 16 | let either = 17 | if (char < 97) 18 | left(()60) 19 | else 20 | right(62); 21 | 22 | //map: (Either(A, B), (A) C, (B) C) C 23 | let map = (e, l, r) 24 | if (is_left(e)) 25 | l(left_0(e)) 26 | else 27 | r(right_0(e)); 28 | 29 | map(either, (f) write(f()), (i) write(i)); 30 | write(10); 31 | map(either, (f) write(f()), (i) write(i)); 32 | write(10); 33 | 34 | let rec readIntImpl = (acc) { 35 | let char = read(); 36 | if (char == 10 || char == 13) 37 | right(acc) 38 | else if (char >= 48 && char <= 57) 39 | readIntImpl(acc * 10 + char - 48) 40 | else 41 | left(-1) 42 | }; 43 | 44 | let rec writeIntImpl = (i) { 45 | if (i / 10) 46 | writeIntImpl(i / 10); 47 | write(i % 10 + 48) 48 | }; 49 | 50 | let writeInt = (i) 51 | if (i < 0) { 52 | write(45); 53 | writeIntImpl(-i) 54 | } else 55 | writeIntImpl(i); 56 | 57 | let readInt = () readIntImpl(0); 58 | 59 | map(readInt(), (l) write(97+4), (r) writeInt(r)); 60 | write(10); 61 | map(readInt(), (l) write(97+4), (r) writeInt(r)); 62 | write(10); 63 | 64 | let rec forever = (f) { 65 | f(); 66 | forever(f) 67 | }; 68 | 69 | let myList = cons(1, cons(2, cons(3, nil()))); 70 | 71 | let rec len = (l) 72 | if (is_nil(l)) 73 | 0 74 | else 75 | 1 + len(cons_1(l)); 76 | 77 | writeInt(len(myList)) 78 | 79 | //forever(() write(97 + 5)) 80 | 81 | } -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # CopperKitten 2 | 3 | ## An exercise in programming language design and implementation 4 | 5 | See [this post](https://colinholzman.xyz/2019/04/17/copper-kitten) for more information. -------------------------------------------------------------------------------- /runtime/bitmap.h: -------------------------------------------------------------------------------- 1 | 2 | 3 | #ifndef BITMAP_H 4 | #define BITMAP_H 5 | 6 | #include 7 | #include 8 | 9 | static inline void bitmap_foreach( 10 | intptr_t *bm, //pointer to the bitmap 11 | intptr_t size, //size of the bitmap (in bits) 12 | void(*cb)(intptr_t i, void *ctx), //callback to be called with the index of each 1 bit 13 | void *cb_ctx) //pointer to context for the callback 14 | { 15 | static intptr_t bits_per_word = CHAR_BIT * sizeof(intptr_t); 16 | intptr_t bit_index = 0; 17 | for (intptr_t word_index = 0; bit_index < size; word_index++) { 18 | bit_index = word_index * bits_per_word; 19 | if (bm[word_index] == 0) { 20 | bit_index += bits_per_word; 21 | } else { 22 | //not zero, have to find some bits 23 | for (intptr_t current_word_bit_i = 0, mask = 1; 24 | current_word_bit_i + word_index * bits_per_word < size 25 | && current_word_bit_i < bits_per_word; 26 | current_word_bit_i++, 27 | mask <<= 1) { 28 | //loop through the current word 29 | if (bm[word_index] & mask) { 30 | cb(bit_index, cb_ctx); 31 | } 32 | //increment bit_index 33 | bit_index++; 34 | } 35 | } 36 | } 37 | } 38 | 39 | #endif 40 | 41 | -------------------------------------------------------------------------------- /runtime/builtin_cfuns.c: -------------------------------------------------------------------------------- 1 | 2 | 3 | #include "vm.h" 4 | 5 | void native_read(struct vm *vm) { 6 | //read char 7 | char c; 8 | scanf("%c", &c); 9 | //return as int 10 | vm_push(vm, 1); 11 | vm_alloc(vm, gc_layout_int_array); 12 | vm_push(vm, c); 13 | vm_rstore(vm, 0); 14 | } 15 | 16 | void native_write(struct vm *vm) { 17 | //print arg 0 as char 18 | vm_aload(vm, 0); 19 | vm_rload(vm, 0); 20 | printf("%c", (int)vm_pop(vm)); 21 | //return unit 22 | vm_push(vm, 0); 23 | } 24 | 25 | -------------------------------------------------------------------------------- /runtime/c_static_assert.h: -------------------------------------------------------------------------------- 1 | 2 | 3 | //From RBerteig at https://stackoverflow.com/a/809465 4 | /** A compile time assertion check. 5 | * 6 | * Validate at compile time that the predicate is true without 7 | * generating code. This can be used at any point in a source file 8 | * where typedef is legal. 9 | * 10 | * On success, compilation proceeds normally. 11 | * 12 | * On failure, attempts to typedef an array type of negative size. The 13 | * offending line will look like 14 | * typedef assertion_failed_file_h_42[-1] 15 | * where file is the content of the second parameter which should 16 | * typically be related in some obvious way to the containing file 17 | * name, 42 is the line number in the file on which the assertion 18 | * appears, and -1 is the result of a calculation based on the 19 | * predicate failing. 20 | * 21 | * \param predicate The predicate to test. It must evaluate to 22 | * something that can be coerced to a normal C boolean. 23 | * 24 | * \param file A sequence of legal identifier characters that should 25 | * uniquely identify the source file in which this condition appears. 26 | */ 27 | 28 | #ifndef C_STATIC_ASSERT_H 29 | #define C_STATIC_ASSERT_H 30 | 31 | #define C_STATIC_ASSERT(predicate, file) C_STATIC_ASSERT_IMPL(predicate,__LINE__,file) 32 | 33 | #define C_STATIC_ASSERT_PASTE(a,b) a##b 34 | #define C_STATIC_ASSERT_IMPL(predicate, line, file) \ 35 | typedef char C_STATIC_ASSERT_PASTE(assertion_failed_##file##_,line)[2*!!(predicate)-1]; 36 | 37 | #endif //C_STATIC_ASSERT_H -------------------------------------------------------------------------------- /runtime/copying_gc.h: -------------------------------------------------------------------------------- 1 | 2 | 3 | #ifndef COPYING_GC_H 4 | #define COPYING_GC_H 5 | 6 | #ifdef __cplusplus 7 | extern "C" { 8 | #endif 9 | 10 | #include "gc_interface.h" 11 | 12 | //instance data for garbage collector 13 | //these things should not be touched 14 | struct gc { 15 | //PRIVATE 16 | //pointers to semispaces 17 | intptr_t *a_space; 18 | intptr_t *b_space; 19 | //size of each space (equal) 20 | size_t size; 21 | //to keep track of allocation and 22 | //collection 23 | intptr_t *alloc_ptr; 24 | intptr_t *scan_ptr; 25 | intptr_t *alloc_begin; 26 | intptr_t *alloc_end; 27 | //PRIVATE 28 | }; 29 | 30 | #ifdef __cplusplus 31 | } 32 | #endif 33 | 34 | #endif //COPYING_GC_H 35 | 36 | -------------------------------------------------------------------------------- /runtime/gc_interface.h: -------------------------------------------------------------------------------- 1 | 2 | 3 | #ifndef GC_INTERFACE_H 4 | #define GC_INTERFACE_H 5 | 6 | #ifdef __cplusplus 7 | extern "C" { 8 | #endif 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | //this is intended as a user (pl implementation) 15 | //interface to a generic memory allocator/manager 16 | 17 | //The methods listed below allow users to 18 | //allocate memory using the garbage collector. 19 | //In order to do so, sometimes memory must be 20 | //reclaimed. In order to reclaim memory your 21 | //struct gc instance must be able to find 22 | //and possibly modify references to the memory 23 | //that it manages. This can be done with the 24 | //root_iter parameter. It is a foreach_t function 25 | //that must be implemented by the user in such 26 | //a way as to provide the struct gc instance 27 | //a view of the user's references. An example of 28 | //this can be seen in test/gc/test_gc.c. 29 | 30 | //function type used by gc_* functions to access 31 | //user's root references and to access references 32 | //in allocated objects. 33 | typedef void (*foreach_t)( 34 | void (*cb)(intptr_t **it, void *ctx), 35 | void *cb_ctx, 36 | void *foreach_ctx); 37 | 38 | //forward declaration of gc instance 39 | struct gc; 40 | 41 | //initialize gc with pointer to self, pointer to memory, and size of memory 42 | void gc_init(struct gc *self, intptr_t *mem, size_t size); 43 | 44 | //see gc.c for example layout functions 45 | //layout_ref_array and layout_int_array 46 | //and layout_example_tagged_ints 47 | 48 | //allocate with an explicit layout 49 | intptr_t *gc_alloc_with_layout( 50 | struct gc *self, //pointer to instance 51 | foreach_t root_iter, //pointer to root iterator 52 | void *root_iter_ctx, //root iterator context 53 | intptr_t size, //size of allocation 54 | foreach_t layout); //layout of allocation 55 | 56 | //allocate GC managed array of refs 57 | intptr_t *gc_alloc_ref_array( 58 | struct gc *self, //instance 59 | foreach_t root_iter, //root iterator 60 | void *root_iter_ctx, //root iterator context 61 | intptr_t size); //number of refs 62 | 63 | //allocate GC managed array of ints (not set to zero) 64 | intptr_t *gc_alloc_int_array( 65 | struct gc *self, //instance 66 | foreach_t root_iter, //root iterator 67 | void *root_iter_ctx, //root iterator context 68 | intptr_t size); //number of ints 69 | 70 | //gets the size of an allocation returned from gc_alloc_* 71 | intptr_t gc_get_size(intptr_t *); 72 | 73 | //to call on pointers that are read from memory 74 | //may change the pointer 75 | void gc_read_barrier(struct gc *, intptr_t **); 76 | 77 | //to call on objects that have had 78 | //managed pointers written to them 79 | void gc_write_barrier(struct gc *, intptr_t *); 80 | 81 | //example layout for dynamic language with tagged ints 82 | static inline void gc_layout_example_tagged_ints( 83 | void (*cb)(intptr_t**, void*), 84 | void *cb_ctx, 85 | void *layout_ctx) 86 | { 87 | //call callback for each element if it's a reference 88 | intptr_t *user_ptr = layout_ctx; 89 | for (intptr_t i = 0; i < gc_get_size(user_ptr); ++i) { 90 | //check tag 91 | if ((user_ptr[i] & 1) == 0) { 92 | //it's a pointer 93 | cb((intptr_t**)&user_ptr[i], cb_ctx); 94 | } 95 | } 96 | } 97 | 98 | //builtin layout for array of references 99 | static inline void gc_layout_ref_array( 100 | void (*cb)(intptr_t**, void*), 101 | void *cb_ctx, 102 | void *layout_ctx) 103 | { 104 | //call callback for each element 105 | intptr_t *user_ptr = layout_ctx; 106 | for (intptr_t i = 0; i < gc_get_size(user_ptr); ++i) { 107 | cb((intptr_t**)&user_ptr[i], cb_ctx); 108 | } 109 | } 110 | 111 | //builtin layout for integer arrays 112 | static inline void gc_layout_int_array( 113 | void (*cb)(intptr_t**, void*), 114 | void *cb_ctx, 115 | void *layout_ctx) 116 | { 117 | //does nothing because int array has no references 118 | (void)cb; 119 | (void)cb_ctx; 120 | (void)layout_ctx; 121 | (void)gc_layout_example_tagged_ints; 122 | } 123 | 124 | #ifdef __cplusplus 125 | } 126 | #endif 127 | 128 | #endif //GC_INTERFACE_H 129 | 130 | -------------------------------------------------------------------------------- /runtime/incremental_copying.ods: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/clnhlzmn/CopperKitten/eee91947d8011576ec30a1934c829f651c911505/runtime/incremental_copying.ods -------------------------------------------------------------------------------- /runtime/incremental_copying_gc_pseudo_code.txt: -------------------------------------------------------------------------------- 1 | 2 | 3 | //gc instance variables 4 | //total memory for heap 5 | heap[HEAP_SIZE] 6 | //size of each semispace 7 | space_size = HEAP_SIZE / 2 8 | //a semispace 9 | a_space = heap 10 | //b semispace 11 | b_space = heap + space_size 12 | //to-space pointers 13 | alloc = a_space 14 | end = a_space + space_size 15 | scan = alloc 16 | 17 | swap_space(): 18 | if end is a_space + space_size 19 | //to-space is currently a_space 20 | alloc = b_space 21 | end = b_space + space_size 22 | else 23 | //to-space is currently b_space 24 | alloc = a_space 25 | end = a_space + space_size 26 | //scan always begins pointed to alloc 27 | scan = alloc 28 | 29 | get_color(ptr): 30 | if ptr >= alloc_begin and ptr < alloc_end: 31 | //ptr is in to-space, and therefore is either grey or black 32 | if ptr >= scan: 33 | //ptr is grey (has yet to be scanned) 34 | return grey 35 | else: 36 | //ptr has been scanned and is black 37 | return black 38 | else: 39 | //ptr is not in to-space 40 | return white 41 | 42 | //returns the size of the allocation at ptr 43 | size(ptr): 44 | //implementation detail 45 | 46 | //returns true if the object at ptr has been forwarded 47 | forwarded(ptr): 48 | //implementation detail 49 | 50 | //returns the forwarding address of the object at ptr 51 | get_forward_location(ptr): 52 | //implementation detail 53 | 54 | //sets the forwarding pointer in the object at ptr 55 | set_forward_location(ptr, loc): 56 | //implementation detail 57 | 58 | forward(ptr): 59 | if forwarded(ptr): 60 | return get_forward_location(ptr) 61 | else: 62 | //make sure enough space to copy 63 | assert(end - alloc >= size(ptr)) 64 | //copy object to to-space 65 | memcpy(alloc, ptr, size(ptr)) 66 | //return new address 67 | ret = alloc 68 | //set the to-space address in the from-space version 69 | //of object so we know how to update references to 70 | //the from-space version 71 | set_forward_location(ptr, alloc) 72 | //bump alloc 73 | alloc = alloc + size(ptr) 74 | //return to-space address 75 | return ret 76 | 77 | //forward all roots 78 | forward_roots(): 79 | for ptr by ref in roots: 80 | //enumerating all roots is implementation detail 81 | ptr = forward(ptr) 82 | 83 | //must be called by mutator whenever 84 | //a pointer has been read from memory 85 | //this ensures that the mutator doesn't 86 | //ever have a pointer to a white object 87 | read_barrier(ptr by ref): 88 | if get_color(ptr) is white: 89 | ptr = forward(ptr) 90 | 91 | //bumps pointer and returns last value 92 | alloc_unchecked(size): 93 | ret = alloc 94 | alloc += size 95 | return ret 96 | 97 | //attempts to allocate size words 98 | //not shown here: how alloc knows 99 | //about all roots, how alloc knows 100 | //where pointers are in objects. 101 | alloc(size): 102 | 103 | //check collecting flag 104 | //not sure if there is another way to determine this 105 | if collecting: 106 | //in collection phase 107 | 108 | //scan K grey objects 109 | //K determined by experiment? 110 | //alternatively scan objects until X bytes have been forwarded? 111 | //K must be large enough that new allocations don't fill to-space 112 | //before we're done collecting 113 | for i in [0 K): 114 | for ptr by ref in scan: 115 | //forward all pointers in object at scan ptr 116 | ptr = forward(ptr) 117 | //advance scan ptr to next object 118 | //this also "colors" the last scanned obj black 119 | scan = scan + size(scan) 120 | 121 | //check if any grey objects remain 122 | if scan >= alloc: 123 | //no more grey objects 124 | collecting = false 125 | //and we keep allocating in the current 126 | //space until it's full, then collect again 127 | 128 | //check enough space 129 | assert(end - alloc >= size) 130 | 131 | return alloc_unchecked(size) 132 | 133 | else: 134 | //not in collection phase 135 | 136 | if end - alloc < size: 137 | //not enough space 138 | 139 | //set flag for next time 140 | collecting = true 141 | 142 | //change end, alloc, scan ptrs 143 | swap_space() 144 | 145 | //forward roots to new space 146 | forward_roots() 147 | 148 | //make sure we still have enough space for the new alloc 149 | assert(end - alloc >= size) 150 | 151 | return alloc_unchecked(size) 152 | 153 | else: 154 | //enough space 155 | //alloc normally 156 | 157 | return alloc_unchecked(size) 158 | 159 | 160 | 161 | -------------------------------------------------------------------------------- /runtime/incremental_gc.h: -------------------------------------------------------------------------------- 1 | 2 | 3 | #ifndef INCREMENTAL_COPYING_GC_H 4 | #define INCREMENTAL_COPYING_GC_H 5 | 6 | #ifdef __cplusplus 7 | extern "C" { 8 | #endif 9 | 10 | #include "gc_interface.h" 11 | 12 | struct gc { 13 | //PRIVATE 14 | //pointers to semispaces 15 | intptr_t *a_space; 16 | intptr_t *b_space; 17 | //size of each space (equal) 18 | size_t size; 19 | //to keep track of allocation and 20 | //collection 21 | #ifndef NDEBUG 22 | //for printing the heap 23 | intptr_t *last_alloc; 24 | #endif 25 | intptr_t *alloc; 26 | intptr_t *scan; 27 | intptr_t *begin; 28 | intptr_t *end; 29 | //to know what to do during alloc 30 | bool collecting; 31 | //PRIVATE 32 | }; 33 | 34 | #ifdef __cplusplus 35 | } 36 | #endif 37 | 38 | #endif //INCREMENTAL_COPYING_GC_H 39 | 40 | -------------------------------------------------------------------------------- /runtime/mark_compact_gc.c: -------------------------------------------------------------------------------- 1 | 2 | 3 | #include "mark_compact_gc.h" 4 | #include "c_static_assert.h" 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #define UINTPTR_BIT (CHAR_BIT * sizeof(intptr_t)) 11 | 12 | struct gc_object { 13 | intptr_t size :UINTPTR_BIT - 1; 14 | intptr_t mark :1; 15 | intptr_t layout; 16 | intptr_t forward; 17 | intptr_t user[]; 18 | }; 19 | 20 | #define META_SIZE (sizeof(struct gc_object) / sizeof(intptr_t)) 21 | 22 | C_STATIC_ASSERT(META_SIZE == 3, mark_compact_gc); 23 | 24 | //convert a user pointer to an allocation pointer 25 | static inline struct gc_object *get_gc_ptr(intptr_t *user) { 26 | return (struct gc_object *)(user - META_SIZE); 27 | } 28 | 29 | //gets the size of an allocation returned from gc_alloc_* 30 | intptr_t gc_get_size(intptr_t *ref) { 31 | return get_gc_ptr(ref)->size - META_SIZE; 32 | } 33 | 34 | //create a GC instance with the given memory of the given size 35 | void gc_init(struct gc *self, intptr_t *mem, size_t size) { 36 | /*printf("gc_init: self = %p\r\n", self);*/ 37 | assert(mem); 38 | self->size = size; 39 | self->heap = mem; 40 | self->alloc_ptr = self->heap; 41 | self->alloc_end = self->heap + size; 42 | } 43 | 44 | //callback for root iterator. 45 | //marks the object pointed to by the 46 | //reference pointed to by it 47 | static inline void mark_ref_cb(intptr_t **it, void *ctx) { 48 | assert(it); 49 | (void)ctx; 50 | intptr_t *ref = *it; 51 | if (*it == NULL) { return; } 52 | struct gc_object *obj = get_gc_ptr(ref); 53 | if (obj->mark == 0) { 54 | /*printf("mark_ref_cb: obj = %p\r\n", obj);*/ 55 | obj->mark = 1; 56 | ((foreach_t) obj->layout)(mark_ref_cb, NULL, obj->user); 57 | } 58 | } 59 | 60 | //callback for root iterator. 61 | //to update the reference pointed to by it 62 | static inline void update_ref_address_cb(intptr_t **it, void *ctx) { 63 | assert(it); 64 | (void)ctx; 65 | if (*it == NULL) { return; } 66 | intptr_t **ref = it; 67 | struct gc_object *obj = get_gc_ptr(*ref); 68 | if (obj->forward) { 69 | /*printf("update_ref_address_cb: old = %p, new = %p\r\n", obj, (void*)obj->forward);*/ 70 | *ref = ((struct gc_object *)obj->forward)->user; 71 | ((foreach_t) obj->layout)(update_ref_address_cb, NULL, obj->user); 72 | } 73 | } 74 | 75 | /*static inline void gc_print_heap(struct gc *self) {*/ 76 | /*printf("gc_print_heap\r\n");*/ 77 | /*for (intptr_t *it = self->heap; it < self->alloc_ptr; ) {*/ 78 | /*struct gc_object *obj = (struct gc_object *) it;*/ 79 | /*printf("obj @ %p\r\n", obj);*/ 80 | /*printf(" marked = %d, forward = %p, size = %llu\r\n", obj->mark, (void*)obj->forward, (intptr_t)obj->size);*/ 81 | /*it += obj->size;*/ 82 | /*}*/ 83 | /*}*/ 84 | 85 | //perform collection freeing required_size cells 86 | static inline void gc_collect( 87 | struct gc *self, 88 | foreach_t root_iter, 89 | void *root_iter_ctx, 90 | intptr_t required_size) 91 | { 92 | /*printf("gc_collect begin: alloc=%p\r\n", self->alloc_ptr);*/ 93 | /*gc_print_heap(self);*/ 94 | 95 | //ptr to the beginning of the heap to help with computing new sizes 96 | intptr_t *alloc = self->heap; 97 | 98 | //recursively call mark on the roots 99 | root_iter(mark_ref_cb, NULL, root_iter_ctx); 100 | 101 | //for each object on the heap if it's marked calculate 102 | //it's new address and store in the forward ptr 103 | for (intptr_t *it = self->heap; it < self->alloc_ptr; ) { 104 | struct gc_object *obj = (struct gc_object *) it; 105 | if (obj->mark) { 106 | obj->forward = (intptr_t)alloc; 107 | alloc += obj->size; 108 | } 109 | it += obj->size; 110 | } 111 | 112 | //update the roots with the new addresses (from forward ptr) 113 | //and recursively update references found in those objects 114 | root_iter(update_ref_address_cb, NULL, root_iter_ctx); 115 | 116 | //move marked objects to their new locations 117 | for (intptr_t *it = self->heap; it < self->alloc_ptr; ) { 118 | struct gc_object *obj = (struct gc_object *) it; 119 | if (obj->mark) { 120 | //get forward 121 | intptr_t *forward = (intptr_t*)obj->forward; 122 | //reset meta 123 | obj->forward = (intptr_t)NULL; 124 | obj->mark = 0; 125 | //move object 126 | memcpy(forward, obj, sizeof(intptr_t) * obj->size); 127 | } 128 | it += obj->size; 129 | } 130 | 131 | //update alloc ptr to end of moved objects 132 | self->alloc_ptr = alloc; 133 | 134 | //check success 135 | if ((intptr_t)(self->alloc_end - self->alloc_ptr) < required_size) { 136 | assert(0 && "out of memory"); 137 | } 138 | 139 | /*printf("gc_collect end: alloc=%p\r\n", self->alloc_ptr);*/ 140 | /*gc_print_heap(self);*/ 141 | } 142 | 143 | //simple allocation of size cells with no checking 144 | static inline intptr_t *gc_alloc_unchecked(struct gc *self, intptr_t size) { 145 | /*printf("gc_alloc_unchecked: ret = %p\r\n", self->alloc_ptr);*/ 146 | intptr_t *ret = self->alloc_ptr; 147 | self->alloc_ptr += size; 148 | return ret; 149 | } 150 | 151 | //allocates n Cells, collecting if necessary 152 | static inline intptr_t *gc_alloc( 153 | struct gc *self, 154 | foreach_t root_iter, 155 | void *root_iter_ctx, 156 | intptr_t size) 157 | { 158 | //sz is number of Cells to allocate 159 | if ((intptr_t)(self->alloc_end - self->alloc_ptr) < size) { 160 | gc_collect(self, root_iter, root_iter_ctx, size); 161 | } 162 | return gc_alloc_unchecked(self, size); 163 | } 164 | 165 | //callback for foreach_t. zeros the reference pointed to by it. 166 | //doesn't care about context 167 | static inline void zero_ref_cb(intptr_t **it, void *ctx) { 168 | (void)ctx; 169 | assert(it); 170 | *it = NULL; 171 | } 172 | 173 | //allocate GC managed memory with custom layout 174 | intptr_t *gc_alloc_with_layout( 175 | struct gc *self, 176 | foreach_t root_iter, 177 | void *root_iter_ctx, 178 | intptr_t size, 179 | foreach_t layout) 180 | { 181 | assert(self); 182 | assert(root_iter); 183 | assert(layout); 184 | //get gc_object 185 | struct gc_object *ret = 186 | (struct gc_object *) 187 | gc_alloc(self, root_iter, root_iter_ctx, size + META_SIZE); 188 | //set size 189 | ret->size = size + META_SIZE; 190 | //set the layout pointer 191 | ret->layout = (intptr_t)layout; 192 | ret->forward = (intptr_t)NULL; 193 | ret->mark = 0; 194 | //use the layout to zero the references (giving user ptr as context to layout) 195 | layout(zero_ref_cb, NULL, ret->user); 196 | return ret->user; 197 | } 198 | 199 | //allocate GC managed array of refs 200 | intptr_t *gc_alloc_ref_array( 201 | struct gc *self, 202 | foreach_t root_iter, 203 | void *root_iter_ctx, 204 | intptr_t size) 205 | { 206 | return gc_alloc_with_layout( 207 | self, root_iter, root_iter_ctx, size, gc_layout_ref_array); 208 | } 209 | 210 | //allocate GC managed array of ints (not set to zero) 211 | intptr_t *gc_alloc_int_array( 212 | struct gc *self, 213 | foreach_t root_iter, 214 | void *root_iter_ctx, 215 | intptr_t size) 216 | { 217 | return gc_alloc_with_layout( 218 | self, root_iter, root_iter_ctx, size, gc_layout_int_array); 219 | } 220 | 221 | void gc_read_barrier(struct gc *gc, intptr_t **ref) { 222 | (void)gc; 223 | (void)ref; 224 | } 225 | 226 | void gc_write_barrier(struct gc *gc, intptr_t *ref) { 227 | (void)gc; 228 | (void)ref; 229 | } 230 | -------------------------------------------------------------------------------- /runtime/mark_compact_gc.h: -------------------------------------------------------------------------------- 1 | 2 | 3 | #ifndef MARK_COMPACT_GC_H 4 | #define MARK_COMPACT_GC_H 5 | 6 | #ifdef __cplusplus 7 | extern "C" { 8 | #endif 9 | 10 | #include "gc_interface.h" 11 | 12 | struct gc { 13 | intptr_t *heap; 14 | size_t size; 15 | intptr_t *alloc_ptr; 16 | intptr_t *alloc_end; 17 | }; 18 | 19 | #ifdef __cplusplus 20 | } 21 | #endif 22 | 23 | #endif //MARK_COMPACT_GC_H 24 | 25 | -------------------------------------------------------------------------------- /runtime/test/bitmap/test_bitmap.c: -------------------------------------------------------------------------------- 1 | 2 | 3 | #include 4 | #include 5 | #include "bitmap.h" 6 | 7 | intptr_t bitmap[] = {0b0000000000000000000000001010101010101010101010101010101010101010, 0b0000000000000000000000001010101010101010101010101010101010101010}; 8 | 9 | void bitmap_cb(intptr_t i, void *ctx) { 10 | (void)ctx; 11 | printf("%lld\r\n", i); 12 | } 13 | 14 | int main() { 15 | printf("sizeof(intptr_t)=%lld\r\n", sizeof(intptr_t)); 16 | bitmap_foreach(bitmap, 128, bitmap_cb, NULL); 17 | } -------------------------------------------------------------------------------- /runtime/test/gc/makefile: -------------------------------------------------------------------------------- 1 | 2 | #to make mingw use proper printf format strings like %lld 3 | CFLAGS = -Wall -Wextra -Werror -std=c99 -g -D__USE_MINGW_ANSI_STDIO=1 -fmax-errors=5 -Wno-error=unused-command-line-argument 4 | LDFLAGS = -g 5 | 6 | test: test_gc.o gc.o gc_interface.o 7 | @echo test 8 | gcc $(LDFLAGS) -o test test_gc.o gc.o gc_interface.o 9 | 10 | gc_interface.o: ../../gc_interface.h ../../gc_interface.c 11 | @echo gc.o 12 | gcc $(CFLAGS) -I../../ -c ../../gc_interface.c -o gc_interface.o 13 | 14 | gc.o: ../../copying_gc.c ../../copying_gc.h ../../gc_interface.h ../../gc_interface.c 15 | @echo gc.o 16 | gcc $(CFLAGS) -I../../ -c ../../copying_gc.c -o gc.o 17 | 18 | test_gc.o: test_gc.c gc.o 19 | @echo test_gc.o 20 | gcc $(CFLAGS) -I../../ -c test_gc.c -o test_gc.o 21 | 22 | clean: 23 | rm -rf test_gc.o 24 | rm -rf gc.o 25 | rm -rf test.exe 26 | rm -rf test 27 | -------------------------------------------------------------------------------- /runtime/test/gc/test: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/clnhlzmn/CopperKitten/eee91947d8011576ec30a1934c829f651c911505/runtime/test/gc/test -------------------------------------------------------------------------------- /runtime/test/gc/test_gc.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include "timer.h" 5 | #include "copying_gc.h" 6 | 7 | //forwards yields one root pointed to by root 8 | void roots_foreach(void (*cb)(intptr_t **item, void *ctx), void *cb_ctx, void *foreach_ctx) { 9 | intptr_t **it = foreach_ctx; 10 | cb(it, cb_ctx); 11 | } 12 | 13 | intptr_t mem[1000000]; 14 | 15 | #define OBJ_SIZE (100) 16 | 17 | int main() { 18 | 19 | //printf("%d", __LINE__); 20 | clock_t begin = timer_begin(); 21 | //memory for gc 22 | struct gc gc_inst; 23 | //gc instance 24 | gc_init(&gc_inst, mem, 1000000); 25 | for (int i = 0; i < 10; ++i) { 26 | //printf("%d", __LINE__); 27 | //alloc one ref cell (no roots yet) 28 | intptr_t *root = NULL; 29 | /*printf("main: &root = %p\r\n", &root);*/ 30 | root = gc_alloc_ref_array(&gc_inst, roots_foreach, &root, OBJ_SIZE); 31 | assert(root); 32 | //printf("%d", __LINE__); 33 | assert(gc_get_size(root) == OBJ_SIZE); 34 | //printf("%d", __LINE__); 35 | //store a value in non ref cell 36 | for (int i = 0; i < OBJ_SIZE; ++i) { 37 | root[i] = (intptr_t)gc_alloc_int_array(&gc_inst, roots_foreach, &root, OBJ_SIZE); 38 | assert(root[i]); 39 | assert(gc_get_size((intptr_t*)root[i]) == OBJ_SIZE); 40 | for (unsigned j = 0; j < OBJ_SIZE; ++j) { 41 | ((intptr_t*)root[i])[j] = j; 42 | } 43 | } 44 | //allocate a bunch 45 | for (int i = 0; i < 1000000; ++i) { 46 | //alloc chunks of 10 cells, no refs 47 | intptr_t *a = gc_alloc_int_array(&gc_inst, roots_foreach, &root, 10); 48 | assert(a); 49 | assert(gc_get_size(a) == 10); 50 | /*printf("%d : %d\r\n", __LINE__, i);*/ 51 | //overwrite memory a little 52 | for (int i = 0; i < 10; ++i) { 53 | a[i] = i; 54 | //std::cout << __LINE__ << ":" << i << std::endl; 55 | } 56 | } 57 | //check that our two allocations survived 58 | assert(root); 59 | for (int i = 0; i < OBJ_SIZE; ++i) { 60 | assert(root[i]); 61 | assert(gc_get_size((intptr_t*)root[i]) == OBJ_SIZE); 62 | for (unsigned j = 0; j < OBJ_SIZE; ++j) { 63 | assert(((intptr_t*)root[i])[j] == j); 64 | } 65 | } 66 | } 67 | /*printf("%lld\r\n", ((intptr_t*)root[0])[0]);*/ 68 | printf("elapsed = %f\r\n", timer_end(begin)); 69 | } 70 | 71 | 72 | -------------------------------------------------------------------------------- /runtime/test/incremental_gc/incremental_gc_test.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include "../../timer.h" 5 | #include "../../incremental_copying_gc.h" 6 | 7 | //forwards yields one root pointed to by root 8 | void roots_foreach(void (*cb)(intptr_t **item, void *ctx), void *cb_ctx, void *foreach_ctx) { 9 | intptr_t **it = foreach_ctx; 10 | cb(it, cb_ctx); 11 | } 12 | 13 | #define MEM_SIZE (100) 14 | 15 | intptr_t mem[MEM_SIZE]; 16 | 17 | #define OBJ_SIZE (3) 18 | 19 | #define INT_DATA ((intptr_t)-1) 20 | 21 | void test_gc(void) { 22 | //printf("%d", __LINE__); 23 | clock_t begin = timer_begin(); 24 | //memory for gc 25 | struct gc gc_inst; 26 | //gc instance 27 | gc_init(&gc_inst, mem, MEM_SIZE); 28 | for (int repeat = 0; repeat < 500; ++repeat) { 29 | //printf("%d", __LINE__); 30 | //alloc one ref cell (no roots yet) 31 | intptr_t *root = NULL; 32 | /*printf("main: &root = %p\r\n", &root);*/ 33 | root = gc_alloc_ref_array(&gc_inst, roots_foreach, &root, OBJ_SIZE); 34 | assert(root); 35 | //printf("%d", __LINE__); 36 | assert(gc_get_size(root) == OBJ_SIZE); 37 | //printf("%d", __LINE__); 38 | //store a value in non ref cell 39 | for (int i = 0; i < OBJ_SIZE; ++i) { 40 | root[i] = (intptr_t)gc_alloc_int_array(&gc_inst, roots_foreach, &root, OBJ_SIZE); 41 | assert(root[i]); 42 | assert(gc_get_size((intptr_t*)root[i]) == OBJ_SIZE); 43 | for (unsigned j = 0; j < OBJ_SIZE; ++j) { 44 | ((intptr_t*)root[i])[j] = INT_DATA; 45 | } 46 | } 47 | //allocate a bunch 48 | for (int i = 0; i < 10000; ++i) { 49 | //alloc chunks of 10 cells, no refs 50 | intptr_t *a = gc_alloc_int_array(&gc_inst, roots_foreach, &root, OBJ_SIZE); 51 | assert(a); 52 | assert(gc_get_size(a) == OBJ_SIZE); 53 | /*printf("%d : %d\r\n", __LINE__, i);*/ 54 | //overwrite memory a little 55 | for (int j = 0; j < 10; ++j) { 56 | a[j] = j; 57 | //std::cout << __LINE__ << ":" << i << std::endl; 58 | } 59 | } 60 | //check that our two allocations survived 61 | assert(root); 62 | for (int i = 0; i < OBJ_SIZE; ++i) { 63 | assert(root[i]); 64 | assert(gc_get_size((intptr_t*)root[i]) == OBJ_SIZE); 65 | gc_read_barrier(&gc_inst, &(intptr_t*)root[i]); 66 | for (unsigned j = 0; j < OBJ_SIZE; ++j) { 67 | assert(((intptr_t*)root[i])[j] == INT_DATA); 68 | } 69 | } 70 | } 71 | /*printf("%lld\r\n", ((intptr_t*)root[0])[0]);*/ 72 | printf("elapsed = %f\r\n", timer_end(begin)); 73 | char c = getc(stdin); 74 | } -------------------------------------------------------------------------------- /runtime/test/incremental_gc/incremental_gc_test.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef INCREMENTAL_GC_TEST 3 | #define INCREMENTAL_GC_TEST 4 | 5 | #ifdef __cplusplus 6 | extern "C" { 7 | #endif 8 | 9 | void test_gc(void); 10 | 11 | #ifdef __cplusplus 12 | } 13 | #endif 14 | 15 | #endif //INCREMENTAL_GC_TEST 16 | 17 | -------------------------------------------------------------------------------- /runtime/test/incremental_gc/incremental_gc_test_sln/incremental_gc_test/incremental_gc_test.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | 15.0 23 | {2E5F6B19-BEB4-4DEC-ACD8-A851C045C9F8} 24 | Win32Proj 25 | incrementalgctest 26 | 10.0.17763.0 27 | 28 | 29 | 30 | Application 31 | true 32 | v141 33 | Unicode 34 | 35 | 36 | Application 37 | false 38 | v141 39 | true 40 | Unicode 41 | 42 | 43 | Application 44 | true 45 | v141 46 | Unicode 47 | 48 | 49 | Application 50 | false 51 | v141 52 | true 53 | Unicode 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | true 75 | 76 | 77 | true 78 | 79 | 80 | false 81 | 82 | 83 | false 84 | 85 | 86 | 87 | NotUsing 88 | EnableAllWarnings 89 | Disabled 90 | true 91 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 92 | true 93 | pch.h 94 | C:\code\ck\runtime;C:\code\ck\runtime\test\incremental_gc;%(AdditionalIncludeDirectories) 95 | false 96 | 97 | 98 | Console 99 | true 100 | 101 | 102 | 103 | 104 | NotUsing 105 | Level3 106 | Disabled 107 | true 108 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions) 109 | true 110 | pch.h 111 | %(AdditionalIncludeDirectories) 112 | true 113 | 114 | 115 | Console 116 | true 117 | 118 | 119 | 120 | 121 | NotUsing 122 | EnableAllWarnings 123 | MaxSpeed 124 | true 125 | true 126 | true 127 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 128 | true 129 | pch.h 130 | C:\code\ck\runtime;C:\code\ck\runtime\test\incremental_gc;%(AdditionalIncludeDirectories) 131 | false 132 | 133 | 134 | Console 135 | true 136 | true 137 | true 138 | 139 | 140 | 141 | 142 | NotUsing 143 | Level3 144 | MaxSpeed 145 | true 146 | true 147 | true 148 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 149 | true 150 | pch.h 151 | %(AdditionalIncludeDirectories) 152 | true 153 | 154 | 155 | Console 156 | true 157 | true 158 | true 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | -------------------------------------------------------------------------------- /runtime/test/incremental_gc/incremental_gc_test_sln/incremental_gc_test/incremental_gc_test.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;ipp;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Header Files 20 | 21 | 22 | Header Files 23 | 24 | 25 | Header Files 26 | 27 | 28 | Header Files 29 | 30 | 31 | Header Files 32 | 33 | 34 | 35 | 36 | Source Files 37 | 38 | 39 | Source Files 40 | 41 | 42 | Source Files 43 | 44 | 45 | -------------------------------------------------------------------------------- /runtime/test/incremental_gc/incremental_gc_test_sln/incremental_gc_test/main.cpp: -------------------------------------------------------------------------------- 1 | // incremental_gc_test.cpp : This file contains the 'main' function. Program execution begins and ends there. 2 | // 3 | 4 | #include "../../incremental_gc_test.h" 5 | 6 | int main() 7 | { 8 | test_gc(); 9 | } 10 | 11 | 12 | -------------------------------------------------------------------------------- /runtime/test/incremental_gc/incremental_gc_test_sln/incremental_gc_test_sln.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.28307.136 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "incremental_gc_test", "incremental_gc_test\incremental_gc_test.vcxproj", "{2E5F6B19-BEB4-4DEC-ACD8-A851C045C9F8}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|x64 = Debug|x64 11 | Debug|x86 = Debug|x86 12 | Release|x64 = Release|x64 13 | Release|x86 = Release|x86 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {2E5F6B19-BEB4-4DEC-ACD8-A851C045C9F8}.Debug|x64.ActiveCfg = Debug|x64 17 | {2E5F6B19-BEB4-4DEC-ACD8-A851C045C9F8}.Debug|x64.Build.0 = Debug|x64 18 | {2E5F6B19-BEB4-4DEC-ACD8-A851C045C9F8}.Debug|x86.ActiveCfg = Debug|Win32 19 | {2E5F6B19-BEB4-4DEC-ACD8-A851C045C9F8}.Debug|x86.Build.0 = Debug|Win32 20 | {2E5F6B19-BEB4-4DEC-ACD8-A851C045C9F8}.Release|x64.ActiveCfg = Release|x64 21 | {2E5F6B19-BEB4-4DEC-ACD8-A851C045C9F8}.Release|x64.Build.0 = Release|x64 22 | {2E5F6B19-BEB4-4DEC-ACD8-A851C045C9F8}.Release|x86.ActiveCfg = Release|Win32 23 | {2E5F6B19-BEB4-4DEC-ACD8-A851C045C9F8}.Release|x86.Build.0 = Release|Win32 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | GlobalSection(ExtensibilityGlobals) = postSolution 29 | SolutionGuid = {0EB4A3FA-6496-4A17-8516-527C276C1AA7} 30 | EndGlobalSection 31 | EndGlobal 32 | -------------------------------------------------------------------------------- /runtime/test/incremental_gc/makefile: -------------------------------------------------------------------------------- 1 | 2 | #to make mingw use proper printf format strings like %lld 3 | CFLAGS = -Wall -Wextra -Werror -std=c99 -Og -D__USE_MINGW_ANSI_STDIO=1 -fmax-errors=5 4 | LDFLAGS = -Og 5 | 6 | #-Wno-error=unused-command-line-argument 7 | 8 | test: test_gc.o gc.o 9 | @echo test 10 | gcc $(LDFLAGS) -o test test_gc.o gc.o 11 | 12 | gc.o: ../../incremental_copying_gc.c ../../incremental_copying_gc.h ../../gc_interface.h 13 | @echo gc.o 14 | gcc $(CFLAGS) -I../../ -c ../../incremental_copying_gc.c -o gc.o 15 | 16 | test_gc.o: test_gc.c gc.o 17 | @echo test_gc.o 18 | gcc $(CFLAGS) -I../../ -c test_gc.c -o test_gc.o 19 | 20 | clean: 21 | rm -rf test_gc.o 22 | rm -rf gc.o 23 | rm -rf test.exe 24 | rm -rf test 25 | -------------------------------------------------------------------------------- /runtime/test/incremental_gc/test: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/clnhlzmn/CopperKitten/eee91947d8011576ec30a1934c829f651c911505/runtime/test/incremental_gc/test -------------------------------------------------------------------------------- /runtime/test/incremental_gc/test_gc.c: -------------------------------------------------------------------------------- 1 | 2 | 3 | int main() { 4 | } 5 | 6 | 7 | -------------------------------------------------------------------------------- /runtime/test/mark_compact_gc/makefile: -------------------------------------------------------------------------------- 1 | 2 | #to make mingw use proper printf format strings like %lld 3 | CFLAGS = -Wall -Wextra -Werror -std=c99 -g -D__USE_MINGW_ANSI_STDIO=1 -fmax-errors=5 -Wno-error=unused-command-line-argument 4 | LDFLAGS = -g 5 | 6 | test: test_gc.o gc.o 7 | @echo test 8 | gcc $(LDFLAGS) -o test test_gc.o gc.o 9 | 10 | gc.o: ../../mark_compact_gc.c ../../mark_compact_gc.h 11 | @echo gc.o 12 | gcc $(CFLAGS) -I../../ -c ../../mark_compact_gc.c -o gc.o 13 | 14 | test_gc.o: test_gc.c gc.o 15 | @echo test_gc.o 16 | gcc $(CFLAGS) -I../../ -c test_gc.c -o test_gc.o 17 | 18 | clean: 19 | rm -rf test_gc.o 20 | rm -rf gc.o 21 | rm -rf test.exe 22 | rm -rf test 23 | -------------------------------------------------------------------------------- /runtime/test/mark_compact_gc/test: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/clnhlzmn/CopperKitten/eee91947d8011576ec30a1934c829f651c911505/runtime/test/mark_compact_gc/test -------------------------------------------------------------------------------- /runtime/test/mark_compact_gc/test_gc.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include "timer.h" 5 | #include "mark_compact_gc.h" 6 | 7 | //forwards yields one root pointed to by root 8 | void roots_foreach(void (*cb)(void *item, void *ctx), void *cb_ctx, void *foreach_ctx) { 9 | intptr_t **it = foreach_ctx; 10 | cb(it, cb_ctx); 11 | } 12 | 13 | intptr_t mem[1000000]; 14 | 15 | #define OBJ_SIZE (100) 16 | 17 | int main() { 18 | 19 | //printf("%d", __LINE__); 20 | clock_t begin = timer_begin(); 21 | //memory for gc 22 | struct gc gc_inst; 23 | //gc instance 24 | gc_init(&gc_inst, mem, 1000000); 25 | for (int i = 0; i < 100; ++i) { 26 | //printf("%d", __LINE__); 27 | //alloc one ref cell (no roots yet) 28 | intptr_t *root = NULL; 29 | /*printf("main: &root = %p\r\n", &root);*/ 30 | root = gc_alloc_ref_array(&gc_inst, roots_foreach, &root, OBJ_SIZE); 31 | assert(root); 32 | //printf("%d", __LINE__); 33 | assert(gc_get_size(root) == OBJ_SIZE); 34 | //printf("%d", __LINE__); 35 | //store a value in non ref cell 36 | for (int i = 0; i < OBJ_SIZE; ++i) { 37 | root[i] = (intptr_t)gc_alloc_int_array(&gc_inst, roots_foreach, &root, OBJ_SIZE); 38 | assert(root[i]); 39 | assert(gc_get_size((intptr_t*)root[i]) == OBJ_SIZE); 40 | for (unsigned j = 0; j < OBJ_SIZE; ++j) { 41 | ((intptr_t*)root[i])[j] = j; 42 | } 43 | } 44 | //allocate a bunch 45 | for (int i = 0; i < 1000000; ++i) { 46 | //alloc chunks of 10 cells, no refs 47 | intptr_t *a = gc_alloc_int_array(&gc_inst, roots_foreach, &root, 10); 48 | assert(a); 49 | assert(gc_get_size(a) == 10); 50 | /*printf("%d : %d\r\n", __LINE__, i);*/ 51 | //overwrite memory a little 52 | for (int i = 0; i < 10; ++i) { 53 | a[i] = i; 54 | //std::cout << __LINE__ << ":" << i << std::endl; 55 | } 56 | } 57 | //check that our two allocations survived 58 | assert(root); 59 | for (int i = 0; i < OBJ_SIZE; ++i) { 60 | assert(root[i]); 61 | assert(gc_get_size((intptr_t*)root[i]) == OBJ_SIZE); 62 | for (unsigned j = 0; j < OBJ_SIZE; ++j) { 63 | assert(((intptr_t*)root[i])[j] == j); 64 | } 65 | } 66 | } 67 | /*printf("%lld\r\n", ((intptr_t*)root[0])[0]);*/ 68 | printf("elapsed = %f\r\n", timer_end(begin)); 69 | } 70 | 71 | 72 | -------------------------------------------------------------------------------- /runtime/test/vm/makefile: -------------------------------------------------------------------------------- 1 | 2 | #to make mingw use proper printf format strings like %lld 3 | CFLAGS = -Wall -Wextra -Werror -std=c99 -g -D__USE_MINGW_ANSI_STDIO=1 -fmax-errors=5 4 | LDFLAGS = -g 5 | 6 | test: test_vm.o ../gc/gc.o 7 | gcc $(LDFLAGS) -o test test_vm.o ../gc/gc.o 8 | 9 | test_vm.o: test_vm.c ../../vm.h 10 | gcc $(CFLAGS) -I../../ -c test_vm.c -o test_vm.o 11 | 12 | clean: 13 | rm -rf test_vm.o 14 | rm -rf test.exe 15 | rm -rf test 16 | -------------------------------------------------------------------------------- /runtime/test/vm/test_vm.c: -------------------------------------------------------------------------------- 1 | 2 | 3 | #include 4 | 5 | #include "vm.h" 6 | 7 | #define HEAPSIZE 1000 8 | #define STACKSIZE 100 9 | 10 | intptr_t heap[HEAPSIZE]; 11 | intptr_t stack[STACKSIZE]; 12 | 13 | struct gc gc_inst; 14 | 15 | struct vm vm_inst; 16 | 17 | int main(void) { 18 | gc_init(&gc_inst, heap, HEAPSIZE); 19 | vm_init(&vm_inst, &gc_inst, stack, STACKSIZE); 20 | int8_t program[] = { 21 | //get input 22 | IN, 23 | //process input 24 | PUSH, 3, 25 | ADD, 26 | //print result 27 | OUT, 28 | //halt 29 | PUSH, 0, 30 | JUMP 31 | }; 32 | vm_execute(&vm_inst, program); 33 | printf("success\r\n"); 34 | } 35 | 36 | 37 | -------------------------------------------------------------------------------- /runtime/timer.h: -------------------------------------------------------------------------------- 1 | 2 | 3 | #ifndef TIMER_H 4 | #define TIMER_H 5 | 6 | #include 7 | 8 | static inline clock_t timer_begin(void) { 9 | return clock(); 10 | } 11 | 12 | static inline double timer_end(clock_t begin) { 13 | clock_t end = clock(); 14 | return (double)(end - begin) / CLOCKS_PER_SEC; 15 | } 16 | 17 | #endif //TIMER_H --------------------------------------------------------------------------------