Skip to content

Commit

Permalink
When casting, don't promote already-tagged values, to tagged values.
Browse files Browse the repository at this point in the history
  • Loading branch information
cpressey committed Feb 22, 2022
1 parent 4520d99 commit 27c0b1a
Show file tree
Hide file tree
Showing 8 changed files with 40 additions and 19 deletions.
2 changes: 2 additions & 0 deletions HISTORY.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ Castile 0.5
* Requesting the AST be dumped, will also dump the AST with
type assignments, if an error occurs during type checking.
* Established an abstract base class for compiler backends.
* Fixed a bug where tagged values were being tagged again
during a cast from a union type to another union type.

Castile 0.4
-----------
Expand Down
6 changes: 4 additions & 2 deletions TODO.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,10 @@ TODO
call equal_tagged_value() when you find a union type when
comparing structs deeply. (C backend, probably others)

There appears to be a bug with casting a union type to
itself? The tag in the tagged value is the union?
Actually the idea of deep equality of structs is suspect.
Especially if the visibility of those structs is limited.
Instead users should write their own `equal` functions
(possibly abstract, possibly only testing equivalence.)

Name mangling for compilers (prepend with `_` most likely.)

Expand Down
2 changes: 1 addition & 1 deletion eg/assoc.castile
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ fun lookup(a: assoc, k: string) {
return null as string|void
}
typecase n is assoc {
return lookup(n, k)
return lookup(n, k) as string|void
}
}

Expand Down
10 changes: 7 additions & 3 deletions src/castile/backends/c.py
Original file line number Diff line number Diff line change
Expand Up @@ -348,9 +348,13 @@ def find_field(name):
self.compile(ast.children[0])
self.write('->%s' % ast.value)
elif ast.tag == 'TypeCast':
self.write('tag("%s",(void *)' % str(ast.children[0].type))
self.compile(ast.children[0])
self.write(')')
# If the LHS is not already a union type, promote it to a tagged value.
if isinstance(ast.children[0].type, Union):
self.compile(ast.children[0])
else:
self.write('tag("%s",(void *)' % str(ast.children[0].type))
self.compile(ast.children[0])
self.write(')')
elif ast.tag == 'TypeCase':
self.write_indent('if (is_tag("%s",' % str(ast.children[1].type))
self.compile(ast.children[0])
Expand Down
10 changes: 7 additions & 3 deletions src/castile/backends/javascript.py
Original file line number Diff line number Diff line change
Expand Up @@ -191,9 +191,13 @@ def compile(self, ast):
self.compile(ast.children[0])
self.write('.%s' % ast.value)
elif ast.tag == 'TypeCast':
self.write("['%s'," % str(ast.children[0].type))
self.compile(ast.children[0])
self.write(']')
# If the LHS is not already a union type, promote it to a tagged value.
if isinstance(ast.children[0].type, Union):
self.compile(ast.children[0])
else:
self.write("['%s'," % str(ast.children[0].type))
self.compile(ast.children[0])
self.write(']')
elif ast.tag == 'TypeCase':
self.write('if (')
self.compile(ast.children[0])
Expand Down
11 changes: 8 additions & 3 deletions src/castile/backends/ruby.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from castile.backends.base import BaseCompiler
from castile.types import Union


OPS = {
Expand Down Expand Up @@ -186,9 +187,13 @@ def compile(self, ast):
self.compile(ast.children[0])
self.write('["%s"]' % ast.value)
elif ast.tag == 'TypeCast':
self.write("['%s'," % str(ast.children[0].type))
self.compile(ast.children[0])
self.write(']')
# If the LHS is not already a union type, promote it to a tagged value.
if isinstance(ast.children[0].type, Union):
self.compile(ast.children[0])
else:
self.write("['%s'," % str(ast.children[0].type))
self.compile(ast.children[0])
self.write(']')
elif ast.tag == 'TypeCase':
self.write_indent('if (')
self.compile(ast.children[0])
Expand Down
14 changes: 8 additions & 6 deletions src/castile/backends/stackmac.py
Original file line number Diff line number Diff line change
Expand Up @@ -238,12 +238,14 @@ def compile(self, ast):
elif ast.tag == 'TypeCast':
self.compile(ast.children[0])
t = str(ast.children[0].type)
self.out.write('; tag with "%s"\n' % t)
if self.size_of(ast.children[0].type) == 0:
# special case. there is nothing on the stack
self.out.write('push 0\n')
tag = self.get_tag(t)
self.out.write('tag %d\n' % tag)
# If the LHS is not already a union type, promote it to a tagged value.
if not isinstance(ast.children[0].type, Union):
self.out.write('; tag with "%s"\n' % t)
if self.size_of(ast.children[0].type) == 0:
# special case. there is nothing on the stack
self.out.write('push 0\n')
tag = self.get_tag(t)
self.out.write('tag %d\n' % tag)
elif ast.tag == 'TypeCase':
end_typecase = self.get_label('end_typecase')
self.compile(ast.children[0])
Expand Down
4 changes: 3 additions & 1 deletion src/castile/eval.py
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,9 @@ def eval(self, ast=None):
return v
elif ast.tag == 'TypeCast':
v = self.eval(ast.children[0])
return TaggedValue(typeof(v), v)
if not isinstance(v, TaggedValue):
v = TaggedValue(typeof(v), v)
return v
elif ast.tag == 'TypeCase':
r = self.eval(ast.children[0])
assert isinstance(r, TaggedValue)
Expand Down

0 comments on commit 27c0b1a

Please sign in to comment.