Bring parser, desugarer in Tamsin up to speed. All tests pass.
Cat's Eye Technologies
11 years ago
17 | 17 | |
18 | 18 | desugar(program(L)) = desugar_all(L) → DL & return program(DL). |
19 | 19 | desugar(module(N, L)) = desugar_all(L) → DL & return module(N, DL). |
20 | desugar(production(N, F, E)) = desugar(E) → DE & return production(N, F, DE). | |
20 | desugar(production(N, F, E, Ps)) = desugar(E) → DE & return production(N, F, DE, Ps). | |
21 | 21 | desugar(or(L, R)) = desugar(L) → DL & desugar(R) → DR & return or(DL, DR). |
22 | 22 | desugar(and(L, R)) = desugar(L) → DL & desugar(R) → DR & return and(DL, DR). |
23 | 23 | desugar(not(X)) = desugar(X) → DX & return not(DX). |
30 | 30 | |
31 | 31 | desugar(fold(R, I)) = |
32 | 32 | desugar(R) → DR & |
33 | SET ← set('_1', I) & | |
34 | SEND ← send(DR, '_2') & | |
35 | CAT ← concat('_1', '_2') & | |
36 | ACC ← set('_1', CAT) & | |
37 | RET ← call(prodref('$', 'return'), list('_1', nil)) & | |
33 | SET ← set(term('_1'), I) & | |
34 | SEND ← send(DR, term('_2')) & | |
35 | CAT ← concat(term('_1'), term('_2')) & | |
36 | ACC ← set(term('_1'), CAT) & | |
37 | RET ← call(prodref('$', 'return'), list(term('_1'), nil)) & | |
38 | 38 | return and(and(SET, while(and(SEND, ACC))), RET). |
39 | 39 | |
40 | 40 | desugar(Else) = Else. |
4 | 4 | # REQUIRES lib/tamsin_scanner.tamsin |
5 | 5 | # REQUIRES lib/tamsin_parser.tamsin |
6 | 6 | |
7 | # Note that this may contain support for some features which are not in | |
8 | # the current released or pre-released version. | |
9 | ||
10 | main = tamsin_parser:parse → AST & {" " | "\n"} & "/" & interpret(AST, AST). | |
7 | main = tamsin_parser:parse → AST & tamsin_scanner:skippable & "/" & | |
8 | interpret(AST, AST). | |
11 | 9 | |
12 | 10 | interpret(P, program(L)) = |
13 | 11 | find_main_module_prods(L) → MMPs & |
14 | 12 | find_prod(main, MMPs) → Main & |
15 | 13 | interpret(P, Main). |
16 | 14 | |
17 | interpret(P, production(N, F, E)) = interpret(P, E). | |
18 | interpret(program(L), call(prodref('$', 'return'), list(X, nil))) = return X. | |
19 | interpret(program(L), call(prodref('$', 'expect'), list(X, nil))) = «X». | |
20 | interpret(program(L), call(prodref('$', 'print'), list(X, nil))) = print X. | |
15 | interpret(P, production(N, F, E, Ps)) = interpret(P, E). | |
16 | interpret(program(L), call(prodref('$', 'return'), list(term(X), nil))) = return X. | |
17 | interpret(program(L), call(prodref('$', 'expect'), list(term(X), nil))) = «X». | |
18 | interpret(program(L), call(prodref('$', 'print'), list(term(X), nil))) = print X. | |
21 | 19 | |
22 | 20 | interpret(program(L), call(prodref(M, N), A)) = |
23 | 21 | find_main_module_prods(L) → MMP & |
29 | 27 | interpret(P, not(X)) = !interpret(P, X). |
30 | 28 | interpret(P, while(X)) = {interpret(P, X)}. |
31 | 29 | |
32 | find_main_module_prods(list(module(main, Ps),T)) = Ps. | |
33 | find_main_module_prods(list(H,T)) = find_main_module_prods(T). | |
30 | find_main_module_prods(list(module(main, Ps), T)) = Ps. | |
31 | find_main_module_prods(list(H, T)) = find_main_module_prods(T). | |
34 | 32 | find_main_module_prods(nil) = fail 'no main module'. |
35 | 33 | |
36 | find_prod(N1, list(production(N2, F, E),T)) = | |
37 | $:equal(N1, N2) & return production(N2, F, E) | find_prod(N1, T). | |
38 | find_prod(N, list(H,T)) = find_prod(N, T). | |
34 | find_prod(N1, list(production(N2, F, E, Ps), T)) = | |
35 | $:equal(N1, N2) & return production(N2, F, E, Ps) | find_prod(N1, T). | |
36 | find_prod(N, list(H, T)) = find_prod(N, T). | |
39 | 37 | find_prod(N, nil) = fail 'no ' + N + ' production'. |
38 | 38 | [formals → F] & |
39 | 39 | "=" & |
40 | 40 | expr0 → E & |
41 | return production(N, F, E). | |
41 | return production(N, F, E, nil). | |
42 | 42 | formals = L ← nil & |
43 | 43 | "(" & |
44 | 44 | term → T & L ← list(T, L) & |
50 | 50 | expr0 = expr1 → L & {("|" | "||") & expr1 → R & L ← or(L, R)} & L. |
51 | 51 | expr1 = expr2 → L & {("&" | "&&") & expr2 → R & L ← and(L, R)} & L. |
52 | 52 | expr2 = expr3 → L & ["using" & prodref → P & L ← using(L, P)] & L. |
53 | expr3 = expr4 → L & [("→" | "->") & variable → V & L ← send(L, V)] & L. | |
53 | expr3 = expr4 → L & [("→" | "->") & variable → V & L ← send(L, term(V))] & L. | |
54 | 54 | expr4 = expr5 → L & ("/" & texpr → T & return fold(L, T) | return L). |
55 | 55 | expr5 = "(" & expr0 → E & ")" & E |
56 | | "[" & expr0 → E & "]" & return or(E, call(prodref('$', return), list(nil, nil))) | |
56 | | "[" & expr0 → E & "]" & | |
57 | return or(E, call(prodref('$', return), list(term(nil), nil))) | |
57 | 58 | | "{" & expr0 → E & "}" & return while(E) |
58 | 59 | | "!" & expr5 → E & return not(E) |
59 | | "set" & variable → V & "=" & texpr → T & return set(V, T) | |
60 | | "set" & variable → V & "=" & texpr → T & return set(term(V), T) | |
60 | 61 | | "return" & texpr → T & return call(prodref('$', return), list(T, nil)) |
61 | 62 | | "fail" & texpr → T & return call(prodref('$', fail), list(T, nil)) |
62 | 63 | | "print" & texpr → T & return call(prodref('$', print), list(T, nil)) |
64 | 65 | | "eof" & return call(prodref('$', 'eof'), nil) |
65 | 66 | | terminal |
66 | 67 | | variable → V & |
67 | (("←" | "<-") & texpr → T & return set(V, T) | |
68 | | return call(prodref('$', return), list(V, nil))) | |
68 | (("←" | "<-") & texpr → T & return set(term(V), T) | |
69 | | return call(prodref('$', return), list(term(V), nil))) | |
69 | 70 | | sq_string → T & |
70 | 71 | $:unquote(T, '\'', '\'') → T & |
71 | return call(prodref('$', return), list(T, nil)) | |
72 | return call(prodref('$', return), list(term(T), nil)) | |
72 | 73 | | prodref → P & |
73 | 74 | L ← nil & |
74 | 75 | ["(" & |
79 | 80 | return call(P, L). |
80 | 81 | |
81 | 82 | texpr = term → T & {"+" & term → S & T ← concat(T, S)} & T. |
82 | term = atom → A & L ← nil & ["(" & | |
83 | term → T & L ← list(T, L) & | |
84 | {"," & term → T & L ← list(T, L)} & | |
83 | term = term0 → T & return term(T). | |
84 | term0 = atom → A & L ← nil & ["(" & | |
85 | term0 → T & L ← list(T, L) & | |
86 | {"," & term0 → T & L ← list(T, L)} & | |
85 | 87 | ")"] & |
86 | 88 | reverse(L, nil) → L & |
87 | 89 | $:mkterm(A, L) |
91 | 93 | $:unquote(T, '\'', '\''). |
92 | 94 | |
93 | 95 | terminal = terminal0 → T & return call(prodref('$', expect), list(T, nil)). |
94 | terminal0 = dq_string → T & $:unquote(T, '"', '"') → T & T | |
95 | | ("«" | "<<") & texpr → T & ("»" | ">>") & T. | |
96 | terminal0 = dq_string → T & $:unquote(T, '"', '"') → T & return term(T) | |
97 | | ("«" | "<<") & texpr → T & ("»" | ">>") & return T. | |
96 | 98 | |
97 | 99 | prodref = M ← '' & [modref → M & ":"] & word → P & return prodref(M, P). |
98 | 100 | modref = "$" | word. |
127 | 127 | ) |
128 | 128 | |
129 | 129 | def __str__(self): |
130 | return "production(%s, %s, %s)" % ( | |
130 | return "production(%s, %s, %s, %s)" % ( | |
131 | 131 | self.name, |
132 | 132 | format_list(self.formals), |
133 | 133 | #format_list(self.locals_), |
134 | 134 | self.body, |
135 | #self.next or 'nil' | |
135 | self.next or 'nil' | |
136 | 136 | ) |
137 | 137 | |
138 | 138 | |
293 | 293 | return u"TermNode(%r)" % self.term |
294 | 294 | |
295 | 295 | def __str__(self): |
296 | return "term(%s)" % self.term | |
296 | return "term(%s)" % self.term.repr() | |
297 | 297 | |
298 | 298 | |
299 | 299 | class Using(AST): |
210 | 210 | self.emit('result = tamsin_mkterm(temp_atom, temp_list);') |
211 | 211 | self.emit('ok = 1;') |
212 | 212 | elif name == 'fail': |
213 | self.emit_term(args[0].term, "temp") | |
214 | self.emit("result = temp;") | |
213 | name = self.compile_r(args[0]) | |
214 | self.emit("result = %s;" % name) | |
215 | 215 | self.emit('ok = 0;') |
216 | 216 | else: |
217 | 217 | raise NotImplementedError(name) |
295 | 295 | name_lhs = self.compile_r(ast.lhs); |
296 | 296 | name_rhs = self.compile_r(ast.rhs); |
297 | 297 | name = self.new_name() |
298 | self.emit('struct term *%s = term_concat(%s, %s);' % | |
298 | self.emit('struct term *%s = term_concat(term_flatten(%s), term_flatten(%s));' % | |
299 | 299 | (name, name_lhs, name_rhs) |
300 | 300 | ) |
301 | 301 | return name; |
302 | 302 | elif isinstance(ast, TermNode): |
303 | 303 | name = self.new_name() |
304 | 304 | self.emit_term(ast.term, name); |
305 | self.emit('result = %s;' % name) | |
306 | 305 | return name |
307 | 306 | else: |
308 | 307 | raise NotImplementedError(repr(ast)) |