Skip to content
Browse files

Add While

  • Loading branch information...
1 parent 19ddebd commit 9a41eb1e86c935c0cfa1fa0dac06bdd277dae968 @txus committed Jan 8, 2012
Showing with 50 additions and 29 deletions.
  1. +9 −8 lib/noscript/ast/script.rb
  2. +20 −0 lib/noscript/compiler.rb
  3. +9 −9 lib/noscript/parser/noscript.y
  4. +9 −9 lib/noscript/parser/parser.rb
  5. +3 −3 test/new_test.rb
View
17 lib/noscript/ast/script.rb
@@ -124,13 +124,14 @@ def initialize(line, condition, body, else_body=nil)
@else_body = else_body || NilLiteral.new(line)
end
end
-#
-# class WhileNode < Node
-# attr_reader :condition, :body
-# def initialize(condition, body)
-# @condition = condition
-# @body = body
-# end
-# end
+
+ class WhileNode < Node
+ attr_reader :condition, :body
+ def initialize(line, condition, body)
+ super(line)
+ @condition = condition
+ @body = body
+ end
+ end
end
end
View
20 lib/noscript/compiler.rb
@@ -10,6 +10,7 @@ def initialize(parent=nil)
@generator = Generator.new
parent_scope = parent ? parent.scope : nil
@scope = Scope.new(@generator, parent_scope)
+ @generator.push_state(@scope)
end
def compile(ast, debugging=false)
@@ -182,6 +183,25 @@ def visit_IfNode(o)
done.set!
end
+ def visit_WhileNode(o)
+ set_line(o)
+ brk = g.new_label
+ repeat = g.new_label
+ repeat.set!
+
+ # Evaluate the condition and jump to the end if false
+ o.condition.accept(self)
+ g.gif brk
+
+ # Otherwise, evaluate the body and jump to the start of the loop again.
+ o.body.accept(self)
+ g.pop
+ g.goto repeat
+
+ brk.set!
+ g.push_nil
+ end
+
def finalize
g.local_names = s.variables
g.local_count = s.variables.size
View
18 lib/noscript/parser/noscript.y
@@ -183,14 +183,14 @@ rule
Operator:
# Binary operators
- Expression '||' Expression { result = CallNode.new(val[0], val[1], [val[2]]); result.pos(filename, lineno) }
- | Expression '&&' Expression { result = CallNode.new(val[0], val[1], [val[2]]); result.pos(filename, lineno) }
- | Expression '==' Expression { result = CallNode.new(val[0], val[1], [val[2]]); result.pos(filename, lineno) }
- | Expression '!=' Expression { result = CallNode.new(val[0], val[1], [val[2]]); result.pos(filename, lineno) }
- | Expression '>' Expression { result = CallNode.new(val[0], val[1], [val[2]]); result.pos(filename, lineno) }
- | Expression '>=' Expression { result = CallNode.new(val[0], val[1], [val[2]]); result.pos(filename, lineno) }
- | Expression '<' Expression { result = CallNode.new(val[0], val[1], [val[2]]); result.pos(filename, lineno) }
- | Expression '<=' Expression { result = CallNode.new(val[0], val[1], [val[2]]); result.pos(filename, lineno) }
+ Expression '||' Expression { result = CallNode.new(lineno, val[0], val[1], [val[2]]) }
+ | Expression '&&' Expression { result = CallNode.new(lineno, val[0], val[1], [val[2]]) }
+ | Expression '==' Expression { result = CallNode.new(lineno, val[0], val[1], [val[2]]) }
+ | Expression '!=' Expression { result = CallNode.new(lineno, val[0], val[1], [val[2]]) }
+ | Expression '>' Expression { result = CallNode.new(lineno, val[0], val[1], [val[2]]) }
+ | Expression '>=' Expression { result = CallNode.new(lineno, val[0], val[1], [val[2]]) }
+ | Expression '<' Expression { result = CallNode.new(lineno, val[0], val[1], [val[2]]) }
+ | Expression '<=' Expression { result = CallNode.new(lineno, val[0], val[1], [val[2]]) }
# 1 + 2 => 1.+(2)
# 1 + 2 1 "+" [2]
| Expression '+' Expression { result = CallNode.new(lineno, val[0], val[1], [val[2]]) }
@@ -221,7 +221,7 @@ rule
While:
WHILE Expression Terminator
Expressions
- END { result = WhileNode.new(val[1], val[3]); result.pos(filename, lineno) }
+ END { result = WhileNode.new(lineno, val[1], val[3]) }
;
---- header ----
View
18 lib/noscript/parser/parser.rb
@@ -823,56 +823,56 @@ def _reduce_60(val, _values, result)
module_eval(<<'.,.,', 'noscript.y', 185)
def _reduce_61(val, _values, result)
- result = CallNode.new(val[0], val[1], [val[2]]); result.pos(filename, lineno)
+ result = CallNode.new(lineno, val[0], val[1], [val[2]])
result
end
.,.,
module_eval(<<'.,.,', 'noscript.y', 186)
def _reduce_62(val, _values, result)
- result = CallNode.new(val[0], val[1], [val[2]]); result.pos(filename, lineno)
+ result = CallNode.new(lineno, val[0], val[1], [val[2]])
result
end
.,.,
module_eval(<<'.,.,', 'noscript.y', 187)
def _reduce_63(val, _values, result)
- result = CallNode.new(val[0], val[1], [val[2]]); result.pos(filename, lineno)
+ result = CallNode.new(lineno, val[0], val[1], [val[2]])
result
end
.,.,
module_eval(<<'.,.,', 'noscript.y', 188)
def _reduce_64(val, _values, result)
- result = CallNode.new(val[0], val[1], [val[2]]); result.pos(filename, lineno)
+ result = CallNode.new(lineno, val[0], val[1], [val[2]])
result
end
.,.,
module_eval(<<'.,.,', 'noscript.y', 189)
def _reduce_65(val, _values, result)
- result = CallNode.new(val[0], val[1], [val[2]]); result.pos(filename, lineno)
+ result = CallNode.new(lineno, val[0], val[1], [val[2]])
result
end
.,.,
module_eval(<<'.,.,', 'noscript.y', 190)
def _reduce_66(val, _values, result)
- result = CallNode.new(val[0], val[1], [val[2]]); result.pos(filename, lineno)
+ result = CallNode.new(lineno, val[0], val[1], [val[2]])
result
end
.,.,
module_eval(<<'.,.,', 'noscript.y', 191)
def _reduce_67(val, _values, result)
- result = CallNode.new(val[0], val[1], [val[2]]); result.pos(filename, lineno)
+ result = CallNode.new(lineno, val[0], val[1], [val[2]])
result
end
.,.,
module_eval(<<'.,.,', 'noscript.y', 192)
def _reduce_68(val, _values, result)
- result = CallNode.new(val[0], val[1], [val[2]]); result.pos(filename, lineno)
+ result = CallNode.new(lineno, val[0], val[1], [val[2]])
result
end
.,.,
@@ -949,7 +949,7 @@ def _reduce_78(val, _values, result)
module_eval(<<'.,.,', 'noscript.y', 223)
def _reduce_79(val, _values, result)
- result = WhileNode.new(val[1], val[3]); result.pos(filename, lineno)
+ result = WhileNode.new(lineno, val[1], val[3])
result
end
.,.,
View
6 test/new_test.rb
@@ -95,8 +95,8 @@ def test_compile_if_else
assert_equal 2, @compiler.compile("if false; 1; else; 2; end").call
end
- # def test_compile_while
- # assert_equal [:while], @compiler.compile("while true; 1; end")
- # end
+ def test_compile_while
+ assert_equal 10, @compiler.compile("a = 3; while a < 10; a = a + 1; end; a").call
+ end
end
end

0 comments on commit 9a41eb1

Please sign in to comment.
Something went wrong with that request. Please try again.