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

Commit

Permalink
Fixed few things
Browse files Browse the repository at this point in the history
  • Loading branch information
deathbeam committed May 15, 2016
1 parent de1f9c8 commit 7fa6e10
Show file tree
Hide file tree
Showing 5 changed files with 113 additions and 102 deletions.
5 changes: 3 additions & 2 deletions examples/compilertest.spoon
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import Sys.print

@message = "Hello"

canvas = js.Browser.document

a = 10
a = 15 + 8 * 6 / 7 + (8 - 7)

Expand All @@ -18,10 +20,9 @@ hash = [
test = (a = 5) ->
print "Jajaja"


[ foo, bar ] = baz
[ a, b ] = hello(world)
[ a: bar, b: baz] = hello(world)
[ a: bar, b: baz ] = hello(world)

log-message = (message = "hello") ->
message = "bb"
Expand Down
28 changes: 28 additions & 0 deletions examples/draw.spoon
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
graphic = [["color":"f68712","path":[["x":45,"y":12],["x":12,"y":45],["x":45,"y":78],["x":78,"y":45],["x":45,"y":12]]],["color":"fab20b","path":[["x":2,"y":1],["x":45,"y":12],["x":12,"y":45],["x":2,"y":1]]],["color":"f89c0e","path":[["x":2,"y":89],["x":12,"y":45],["x":45,"y":78],["x":2,"y":89]]],["color":"f47216","path":[["x":89,"y":1],["x":78,"y":45],["x":45,"y":12],["x":89,"y":1]]],["color":"f25c19","path":[["x":89,"y":89],["x":45,"y":78],["x":78,"y":45],["x":89,"y":89]]],["color":"fbc707","path":[["x":45,"y":12],["x":2,"y":1],["x":23,"y":1],["x":45,"y":12]]],["color":"fbc707","path":[["x":45,"y":12],["x":89,"y":1],["x":67,"y":1],["x":45,"y":12]]],["color":"f68712","path":[["x":45,"y":78],["x":89,"y":89],["x":67,"y":89],["x":45,"y":78]]],["color":"f25c19","path":[["x":45,"y":78],["x":2,"y":89],["x":23,"y":89],["x":45,"y":78]]],["color":"fff200","path":[["x":12,"y":45],["x":2,"y":89],["x":2,"y":67],["x":12,"y":45]]],["color":"fff200","path":[["x":12,"y":45],["x":2,"y":1],["x":2,"y":23],["x":12,"y":45]]],["color":"f1471d","path":[["x":78,"y":45],["x":89,"y":89],["x":89,"y":67],["x":78,"y":45]]],["color":"f1471d","path":[["x":78,"y":45],["x":89,"y":1],["x":89,"y":23],["x":78,"y":45]]]]

draw = ->
# FIXME: js.Browser.document, and not .cument
canvas = js.Browser.cument.createCanvasElement!
canvas.width = 400
canvas.height = 400
js.Browser.cument.body.appendChild(canvas)

ctx = canvas.getContext2d!

for part in graphic
path = part.path
ctx.beginPath!
ctx.fillStyle = "\##{part.color}"

# FIXME: chain should have higher priority than range
for i in 0..path.length
point = part.path[i]

if i == 0
ctx.moveTo(point.x, point.y)
else
ctx.lineTo(point.x, point.y)

ctx.fill!

draw!
117 changes: 55 additions & 62 deletions lib/spoon/compiler.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ def initialize(path = "main")
:if => If,
:for => For,
:while => While,
:assign => Assign,
:op => Operation,
:call => Call,
:new => New,
Expand Down Expand Up @@ -142,50 +141,70 @@ def compile
end
end

class Assign < Base
class Operation < Base
@@assign_counter = 0

def compile
children = @node.children.dup
operator = children.shift.to_s

left = children.shift
right = children.shift

if left.option :is_array
assign_name = "__assign#{@@assign_counter}"
@content << "var #{assign_name} = #{compile_next(right)};\n"
@@assign_counter += 1
@content << "(" if @parent.node.type == :op

left.children.each_with_index do |child, index|
child_name = compile_next(child)
@content << @parent.tab
scope_name(child)
@content << "#{child_name} = #{assign_name}[#{index}]"
@content << ";\n" unless left.children.last == child
end
elsif left.option :is_hash
assign_name = "__assign#{@@assign_counter}"
@content << "var #{assign_name} = #{compile_next(right)};\n"
@@assign_counter += 1

left.children.each do |child|
child_children = child.children.dup
child_children.shift
child_alias_node = child_children.shift
child_alias = compile_next(child_alias_node)
child_name = compile_next(child_children.shift)
@content << @parent.tab
scope_name(child_alias_node)
@content << "#{child_alias} = #{assign_name}.#{child_name}"
@content << ";\n" unless left.children.last == child
case @node.option :operation
when :infix
left = children.shift
right = children.shift

if operator == "="
if left.option :is_array
assign_name = "__assign#{@@assign_counter}"
@content << "var #{assign_name} = #{compile_next(right)};\n"
@@assign_counter += 1

left.children.each_with_index do |child, index|
child_name = compile_next(child)
@content << @parent.tab
scope_name(child)
@content << "#{child_name} = #{assign_name}[#{index}]"
@content << ";\n" unless left.children.last == child
end
elsif left.option :is_hash
assign_name = "__assign#{@@assign_counter}"
@content << "var #{assign_name} = #{compile_next(right)};\n"
@@assign_counter += 1

left.children.each do |child|
child_children = child.children.dup
child_children.shift
child_alias_node = child_children.shift
child_alias = compile_next(child_alias_node)
child_name = compile_next(child_children.shift)
@content << @parent.tab
scope_name(child_alias_node)
@content << "#{child_alias} = #{assign_name}.#{child_name}"
@content << ";\n" unless left.children.last == child
end
else
@content << "(" if @parent.node.type == :op
@content << scope_name(left)
@content << " #{operator} " << compile_next(right)
@content << ")" if @parent.node.type == :op
end
else
@content << compile_next(left)
@content << " #{operator} "
@content << compile_next(right)
end
else
@content << "(" if @parent.node.type == :op
@content << scope_name(left)
@content << " = " << compile_next(right)
@content << ")" if @parent.node.type == :op
when :prefix
@content << operator
@content << compile_next(children.shift)
when :suffix
@content << compile_next(children.shift)
@content << operator
end

@content << ")" if @parent.node.type == :op

super
end

Expand Down Expand Up @@ -215,32 +234,6 @@ def scope_name(node)
end
end

class Operation < Base
def compile
children = @node.children.dup
operator = children.shift.to_s

@content << "(" if @parent.node.type == :op

case @node.option :operation
when :infix
@content << compile_next(children.shift)
@content << " #{operator} "
@content << compile_next(children.shift)
when :prefix
@content << operator
@content << compile_next(children.shift)
when :suffix
@content << compile_next(children.shift)
@content << operator
end

@content << ")" if @parent.node.type == :op

super
end
end

class Value < Base
def compile
children = @node.children.dup
Expand Down
61 changes: 27 additions & 34 deletions lib/spoon/parser.rb
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ def initialize
(
whitespace.maybe >>
import.repeat >>
expression.repeat(1) >>
expression.repeat >>
whitespace.maybe
).as(:root)
}
Expand Down Expand Up @@ -68,30 +68,39 @@ def initialize
# TODO: Add decorators (postfix if, unless, for and while)
rule(:expression) {
space.maybe >>
(assign | operation | value) >>
(unary_operation | operation | value) >>
endline.maybe
}

# Matches operation
rule(:operation) {
unary_operation | infix_expression(
infix_expression(
unary_operation | parens(value) | parens(operation, true),
[RANGE(), 13, :left],
[DOT(), 12, :left],
[MUL(), 11, :left],
[ADD(), 10, :left],
[SHIFT(), 9, :left],
[COMPARE(), 8, :left],
[EQ(), 7, :left],
[BAND(), 6, :left],
[BXOR(), 5, :left],
[BOR(), 4, :left],
[AND(), 3, :left],
[OR(), 2, :left],
[CASSIGN(), 1, :right]
[RANGE(), 14, :left],
[DOT(), 13, :left],
[MUL(), 12, :left],
[ADD(), 11, :left],
[SHIFT(), 10, :left],
[COMPARE(), 9, :left],
[EQ(), 8, :left],
[BAND(), 7, :left],
[BXOR(), 6, :left],
[BOR(), 5, :left],
[AND(), 4, :left],
[OR(), 3, :left],
[CASSIGN(), 2, :right],
[ASSIGN(), 1, :right]
)
}

# Matches unary operation
# example: !foo
# TODO: Enable spaces between operator and value
rule(:unary_operation) {
((INCREMENT() | UNARY()).as(:o) >> value.as(:r)) |
(value.as(:l) >> INCREMENT().as(:o))
}

# Matches object construction
# example: new Foo!
rule(:construct) {
Expand All @@ -101,22 +110,6 @@ def initialize
).as(:construct)
}

# Matches assign
# example: foo = bar
rule(:assign) {
(
parens(value).as(:l) >> ASSIGN() >> expression.as(:r)
).as(:assign)
}

# Matches unary operation
# example: !foo
# TODO: Enable spaces between operator and value
rule(:unary_operation) {
((INCREMENT() | UNARY()).as(:o) >> value.as(:r)) |
(value.as(:l) >> INCREMENT().as(:o))
}

# Matches value
rule(:value) {
condition |
Expand Down Expand Up @@ -176,7 +169,7 @@ def initialize
skip_key >>
(
match['a-z'] >>
match['a-zA-Z\-'].repeat
match['a-zA-Z0-9\-'].repeat
).as(:ident)
}

Expand All @@ -185,7 +178,7 @@ def initialize
skip_key >>
(
match['A-Z'] >>
match['a-zA-Z\-'].repeat
match['a-zA-Z0-9\-'].repeat
).as(:type)
}

Expand Down
4 changes: 0 additions & 4 deletions lib/spoon/transformer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -91,10 +91,6 @@ class Transformer < Parslet::Transform
AST::Node.new :param, [ name, value]
}

rule(:assign => { :l => simple(:left), :r => simple(:right) }) {
AST::Node.new :assign, [ left, right ]
}

rule(:l => simple(:left), :o => simple(:op), :r => simple(:right)) {
AST::Node.new :op, [ op.to_op, left, right ], :operation => :infix
}
Expand Down

0 comments on commit 7fa6e10

Please sign in to comment.