diff --git a/README.md b/README.md index 49213b6..2ab4295 100644 --- a/README.md +++ b/README.md @@ -1080,7 +1080,7 @@ Each of the individual types named in the union type must be unique. | } ? bad union type -Cannot promote a union type to itself. +One can, vacuously, promote a union type to itself. | fun main() { | a = 20; @@ -1089,20 +1089,20 @@ Cannot promote a union type to itself. | d = c as integer|string | print("ok") | } - ? bad cast + = ok -Can promote a union type to another union type, so long as it is a superset. (TODO) +One can promote a union type to another union type, so long as it is a superset. - /| fun main() { - /| a = 20; - /| b = 30; - /| c = a + b as integer|string - /| d = c as integer|string|void - /| print("ok") - /| } - /= ok + | fun main() { + | a = 20; + | b = 30; + | c = a + b as integer|string + | d = c as integer|string|void + | print("ok") + | } + = ok -Cannot promote a union type to a union type that is not a superset. +One cannot promote a union type to a union type that is not a superset. | fun main() { | a = 20; diff --git a/TODO.md b/TODO.md index fbf0345..4c4cdde 100644 --- a/TODO.md +++ b/TODO.md @@ -30,8 +30,6 @@ Other backends (Python? Java? CIL? Scheme?) ### Design ### -Promote union type to bigger union type (e.g. `string|int` => `string|int|void`) - Don't output final value. Command-line arguments passed to `main`. (`sysmain`?) Convenience: diff --git a/src/castile/checker.py b/src/castile/checker.py index 6870304..e756161 100644 --- a/src/castile/checker.py +++ b/src/castile/checker.py @@ -302,15 +302,15 @@ def type_of(self, ast): elif ast.tag == 'StructDefn': ast.type = Void() elif ast.tag == 'TypeCast': - val_t = self.type_of(ast.children[0]) - uni_t = self.type_of(ast.children[1]) - if not isinstance(uni_t, Union): - raise CastileTypeError('bad cast, not a union: %s' % uni_t) - if not uni_t.contains(val_t): + value_t = self.type_of(ast.children[0]) + union_t = self.type_of(ast.children[1]) + if not isinstance(union_t, Union): + raise CastileTypeError('bad cast, not a union: %s' % union_t) + if not union_t.contains(value_t): raise CastileTypeError( - 'bad cast, %s does not include %s' % (uni_t, val_t) + 'bad cast, %s does not include %s' % (union_t, value_t) ) - ast.type = uni_t + ast.type = union_t else: raise NotImplementedError(repr(ast)) return ast.type diff --git a/src/castile/types.py b/src/castile/types.py index 93c4c36..5be3891 100644 --- a/src/castile/types.py +++ b/src/castile/types.py @@ -53,9 +53,11 @@ class Union(Type): def __init__(self, content_types): self.content_types = content_types - def contains(self, type): + def contains(self, type_): + if isinstance(type_, Union): + return all([self.contains(t) for t in type_.content_types]) for member in self.content_types: - if type == member: + if type_ == member: return True return False