Skip to content

Commit

Permalink
[ast,parser] Allow types to define supertypes using the type restrict…
Browse files Browse the repository at this point in the history
…ion syntax.
  • Loading branch information
faultyserver committed Feb 4, 2018
1 parent b0dcb27 commit 68cc3ea
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 7 deletions.
3 changes: 2 additions & 1 deletion .sentry.yml
Expand Up @@ -5,7 +5,8 @@
# every time any of the source files changes.
display_name: myst specs
info: true
build: crystal spec
# `|| echo` makes sure that sentry keeps running even if there the specs fail.
build: crystal spec --no-debug || echo ''
run: # nothing to do
watch:
- ./src/myst/**/*.cr
Expand Down
37 changes: 37 additions & 0 deletions spec/syntax/parser_spec.cr
Expand Up @@ -1025,6 +1025,43 @@ describe "Parser" do
), TypeDef.new("Thing", body: e(TypeDef.new("Part")))


# Inheritance

# Types can inherit from other types using a syntax similar to type restrictions
it_parses %q(deftype Foo : Bar; end), TypeDef.new("Foo", supertype: c("Bar"))
# The supertype can be a namespaced name
it_parses %q(deftype Foo : Bar.Baz; end), TypeDef.new("Foo", supertype: Call.new(c("Bar"), "Baz"))
it_parses %q(deftype Foo : Bar.Baz.Foo; end), TypeDef.new("Foo", supertype: Call.new(Call.new(c("Bar"), "Baz"), "Foo"))
# Type supertype can also be interpolated
it_parses %q(deftype Foo : <get_supertype>; end), TypeDef.new("Foo", supertype: i(Call.new(nil, "get_supertype")))
# If a colon is given, a type name is required
it_does_not_parse %q(deftype Foo : ; end)
it_does_not_parse %q(
deftype Foo :
end
)
# The separating colon must be padded with a space to avoid confusion with a Symbol.
it_does_not_parse %q(
deftype Foo:Bar; end
)
# The supertype name must be given on the same line as the type
it_does_not_parse %q(
deftype Foo :
Bar
end
)
it_does_not_parse %q(
deftype Foo
: Bar
end
)
# Type paths must be given with no spaces
it_does_not_parse %q(deftype Foo : Bar . Baz; end)
# Inheritance is only valid on type definitions
it_does_not_parse %q(defmodule Foo : Bar; end)



# Type methods

it_parses %q(
Expand Down
9 changes: 5 additions & 4 deletions src/myst/syntax/ast.cr
Expand Up @@ -784,14 +784,15 @@ module Myst
# A type definition. TypeDefs are similar to ModuleDefs, but define a data
# type that can be instantiated similar to how Literals create primitives.
#
# 'deftype' const
# 'deftype' const : const
# body
# 'end'
class TypeDef < Node
property name : String
property body : Node
property name : String
property body : Node
property! supertype : Call | Const | ValueInterpolation | Nil

def initialize(@name, @body=Nop.new)
def initialize(@name, @body=Nop.new, @supertype=nil)
end

def accept_children(visitor)
Expand Down
30 changes: 28 additions & 2 deletions src/myst/syntax/parser.cr
Expand Up @@ -377,17 +377,43 @@ module Myst
skip_space
name = expect(Token::Type::CONST).value
skip_space
# Type definitions can optionally provide a supertype to inherit from.
supertype =
if accept(Token::Type::COLON)
skip_space
parse_type_path
end
skip_space
expect_delimiter
skip_space_and_newlines

if finish = accept(Token::Type::END)
return TypeDef.new(name, Nop.new).at(start.location).at_end(finish.location)
return TypeDef.new(name, Nop.new, supertype: supertype).at(start.location).at_end(finish.location)
else
push_var_scope
body = parse_code_block(Token::Type::END)
finish = expect(Token::Type::END)
pop_var_scope
return TypeDef.new(name, body).at(start.location).at_end(finish.location)
return TypeDef.new(name, body, supertype: supertype).at(start.location).at_end(finish.location)
end
end

def parse_type_path
case current_token.type
when Token::Type::CONST
token = current_token
read_token
path = Const.new(token.value).at(token.location)
while accept(Token::Type::POINT)
next_path_part = expect(Token::Type::CONST)
path = Call.new(path, next_path_part.value).at(path.location).at_end(next_path_part.location)
end

path
when Token::Type::LESS
parse_value_interpolation
else
raise ParseError.new(current_location, "Expected supertype after colon in type definition")
end
end

Expand Down

0 comments on commit 68cc3ea

Please sign in to comment.