git @ Cat's Eye Technologies Castile / 0183881
Minimal name-mangling in Ruby backend. Demo "Parse, don't validate". Chris Pressey 3 years ago
2 changed file(s) with 78 addition(s) and 30 deletion(s). Raw diff Collapse all Expand all
11221122
11231123 You may want to use helper functions to hide this ugliness.
11241124
1125 /| struct list {
1126 /| value: string;
1127 /| next: list|void;
1128 /| }
1129 /| fun singleton(v: string) {
1130 /| make list(value:v, next:null as list|void)
1131 /| }
1132 /| fun cons(v: string, l: list) {
1133 /| make list(value:v, next:l as list|void)
1134 /| }
1135 /| fun nth(n, l: list) {
1136 /| u = l as list|void;
1137 /| v = u;
1138 /| k = n;
1139 /| while k > 1 {
1140 /| typecase u is void { break; }
1141 /| typecase u is list { v = u.next; }
1142 /| u = v;
1143 /| k = k - 1;
1144 /| }
1145 /| return u
1146 /| }
1147 /| main = fun() {
1148 /| l = cons("first", singleton("second"));
1149 /| g = nth(2, l);
1150 /| typecase g is list { print(g.value); }
1151 /| }
1152 /= second
1125 | struct list {
1126 | value: string;
1127 | next: list|void;
1128 | }
1129 |
1130 | fun empty() {
1131 | return null as list|void
1132 | }
1133 |
1134 | fun cons(v: string, l: list|void) {
1135 | make list(value:v, next:l) as list|void
1136 | }
1137 |
1138 | fun nth(n, l: list|void) {
1139 | u = l;
1140 | v = u;
1141 | k = n;
1142 | while k > 1 {
1143 | typecase u is void { break; }
1144 | typecase u is list { v = u.next; }
1145 | u = v;
1146 | k = k - 1;
1147 | }
1148 | return u
1149 | }
1150 |
1151 | main = fun() {
1152 | l = cons("first", cons("second", cons("third", empty())));
1153 | h = nth(2, l);
1154 | typecase h is list { print(h.value); }
1155 | }
1156 = second
1157
1158 And in fact, you can restrict the union types to smaller sets to
1159 better indicate the allowable types of the functions. For example,
1160 `cons` always returns a list, so that should be its return type,
1161 not `list|void`. Likewise, `nth` requires a list. In this way we
1162 can implement some of the "Parse, don't Validate" approach.
1163
1164 | struct list {
1165 | value: string;
1166 | next: list|void;
1167 | }
1168 |
1169 | fun cons(v: string, l: list) {
1170 | make list(value:v, next:l as list|void)
1171 | }
1172 |
1173 | fun singleton(v: string) {
1174 | make list(value:v, next:null as list|void)
1175 | }
1176 |
1177 | fun nth(n, l: list) {
1178 | u = l as list|void;
1179 | v = u;
1180 | k = n;
1181 | while k > 1 {
1182 | typecase u is void { break; }
1183 | typecase u is list { v = u.next; }
1184 | u = v;
1185 | k = k - 1;
1186 | }
1187 | return u
1188 | }
1189 |
1190 | main = fun() {
1191 | l = cons("first", cons("second", singleton("third")));
1192 | h = nth(2, l);
1193 | typecase h is list { print(h.value); }
1194 | }
1195 = second
11531196
11541197 Structs may be empty.
11551198
8282 self.out.write(' ' * self.indent)
8383 self.out.write(x)
8484
85 def mangle(self, ident):
86 if ident.startswith('next'):
87 return '{}_'.format(ident)
88 return ident
89
8590 def compile(self, ast):
8691 if ast.tag == 'Program':
8792 self.write(PRELUDE)
116121 for child in ast.children:
117122 self.compile(child)
118123 elif ast.tag == 'VarDecl':
119 self.write_indent('%s = nil;\n' % ast.value)
124 self.write_indent('%s = nil;\n' % self.mangle(ast.value))
120125 elif ast.tag == 'Block':
121126 for child in ast.children:
122127 self.compile(child)
136141 self.compile(ast.children[1])
137142 self.write(')')
138143 elif ast.tag == 'VarRef':
139 self.write(ast.value)
144 self.write(self.mangle(ast.value))
140145 elif ast.tag == 'FunCall':
141146 self.compile(ast.children[0])
142147 self.write('.call(')