Skip to content
This repository has been archived by the owner on Dec 24, 2023. It is now read-only.

Commit

Permalink
Type system enhancements
Browse files Browse the repository at this point in the history
- Function parameter types
- Function return type

Check examples/classes.spoon for example
  • Loading branch information
deathbeam committed May 20, 2016
1 parent ba29fc1 commit 57e9be8
Show file tree
Hide file tree
Showing 4 changed files with 39 additions and 11 deletions.
8 changes: 4 additions & 4 deletions examples/classes.spoon
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
#!/usr/bin/env coffee

class Point2d
new = (x, y) ->
new = (x : Int, y : Int) : Void ->
@x : Int = x
@y : Int = y

to-string = -> "Point2d: x=#{@x}, y=#{@y}"
to-string = : String -> "Point2d: x=#{@x}, y=#{@y}"

class Point3d < Point2d
new = (x, y, z) ->
new = (x : Int, y : Int, z : Int) : Void ->
super x, y
@z : Int = z

\override
to-string = -> "Point3d: x=#{@x}, y=#{@y}, z=#{@z}"
to-string = : String -> "Point3d: x=#{@x}, y=#{@y}, z=#{@z}"

point2d = Point2d(100, 200)
trace point2d.to-string!
Expand Down
9 changes: 7 additions & 2 deletions lib/spoon/compiler.rb
Original file line number Diff line number Diff line change
Expand Up @@ -310,7 +310,6 @@ def scope_name(node)

if is_self || is_this
child = node.children.first
is_typed = child.option :is_typed
name = ""
type = true

Expand Down Expand Up @@ -386,7 +385,10 @@ def compile
class Param < Base
def compile
children = @node.children.dup
type = (@node.option(:is_typed) ? children.shift : false)

@content << compile_next(children.shift)
@content << " : #{compile_next(type)}" if type
@content << " = " << compile_next(children.shift) unless children.empty?
super
end
Expand Down Expand Up @@ -480,6 +482,7 @@ def compile
@compiler.scope.add

children = @node.children.dup
type = (@node.option(:is_typed) ? children.shift : false)

@content << "function ("

Expand All @@ -495,7 +498,9 @@ def compile
end
end

@content << ") return "
@content << ") "
@content << ": #{compile_next(type)} " if type
@content << "return "
@content << compile_next(children.last)

@compiler.scope.pop
Expand Down
7 changes: 5 additions & 2 deletions lib/spoon/parser.rb
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ class Parser < Spoon::Util::IndentParser
# Matches typed word
# example: foo as Bar
rule(:typed) {
(ident.as(:name) >> trim(DOUBLE_DOT()) >> type.as(:type)).as(:typed)
(ident.as(:value) >> trim(DOUBLE_DOT()) >> type.as(:type)).as(:typed)
}

# Matches word
Expand Down Expand Up @@ -272,7 +272,9 @@ class Parser < Spoon::Util::IndentParser
# Matches function parameter
# example a = 1
rule(:parameter) {
ident.as(:name) >> (ASSIGN() >> expression.as(:value)).maybe
ident.as(:name) >>
(trim(DOUBLE_DOT()) >> type.as(:type)).maybe >>
(ASSIGN() >> expression.as(:value)).maybe
}

# Matches comma delimited function parameters
Expand All @@ -292,6 +294,7 @@ class Parser < Spoon::Util::IndentParser
rule(:closure) {
(
parameter_list.as(:params).maybe >>
(trim(DOUBLE_DOT()) >> type.as(:type)).maybe >>
whitespace.maybe >>
ARROW() >>
body.as(:body)
Expand Down
26 changes: 23 additions & 3 deletions lib/spoon/transformer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@ class Transformer < Parslet::Transform
AST::Node.new :value, [ value ], :is_self => true
}

rule(:typed => { :name => simple(:name), :type => simple(:type) } ) {
AST::Node.new :value, [ name, type ], :is_typed => true
rule(:typed => { :value => simple(:value), :type => simple(:type) } ) {
AST::Node.new :value, [ value, type ], :is_typed => true
}

rule(:class => { :name => simple(:name), :body => simple(:body) } ) {
Expand Down Expand Up @@ -100,8 +100,16 @@ class Transformer < Parslet::Transform
AST::Node.new :param, [ name ]
}

rule(:param => { :name => simple(:name), :type => simple(:type) }) {
AST::Node.new :param, [ type, name ], :is_typed => true
}

rule(:param => { :name => simple(:name), :value => simple(:value) }) {
AST::Node.new :param, [ name, value]
AST::Node.new :param, [ name, value ]
}

rule(:param => { :name => simple(:name), :type => simple(:type), :value => simple(:value) }) {
AST::Node.new :param, [ type, name, value ], :is_typed => true
}

rule(:l => simple(:left), :o => simple(:op), :r => simple(:right)) {
Expand Down Expand Up @@ -168,6 +176,18 @@ class Transformer < Parslet::Transform
AST::Node.new :closure, params + [ body ]
}

rule(:closure => { :type => simple(:type), :body => simple(:body) }) {
AST::Node.new :closure, [ type, body ], :is_typed => true
}

rule(:closure => { :params => simple(:params), :type => simple(:type), :body => simple(:body) }) {
AST::Node.new :closure, [ type, params, body ], :is_typed => true
}

rule(:closure => { :params => sequence(:params), :type => simple(:type), :body => simple(:body) }) {
AST::Node.new :closure, [ type ] + params + [ body ], :is_typed => true
}

rule(:if => { :condition => simple(:condition), :true => simple(:if_true) }) {
AST::Node.new :if, [ condition, if_true ]
}
Expand Down

0 comments on commit 57e9be8

Please sign in to comment.