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
--------------------------------------------------------------------------------