Skip to content
This repository has been archived by the owner on May 13, 2019. It is now read-only.

Commit

Permalink
And some more changes
Browse files Browse the repository at this point in the history
  • Loading branch information
matthewd committed Nov 20, 2010
1 parent 1e63e20 commit d21fcee
Show file tree
Hide file tree
Showing 8 changed files with 79 additions and 41 deletions.
2 changes: 1 addition & 1 deletion bin/rasp
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ $: << File.join(File.dirname(File.dirname(__FILE__)), "lib")

require 'rasp'

filename = 't/math.vbs'
filename = ARGV.shift || 't/math.vbs'
parse = Rasp::Parser.parse(File.read(filename), :consume => true)
#puts parse.dump

Expand Down
2 changes: 1 addition & 1 deletion lib/rasp/ast.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ def self.math_op(match, op=nil)

def self.binary_op(klass, lhs, ary, op_attr=nil, attr=:rhs)
lhs = lhs.value
ary = ary.matches
ary = ary.matches.dup
until ary.empty?
curr = ary.shift
rhs = curr.send(attr).value
Expand Down
1 change: 0 additions & 1 deletion lib/rasp/ast/block.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ def global; self; end
def bytecode(g)
g.push_state self
statements.each do |s|
p s
s.bytecode(g)
end
g.pop_state
Expand Down
10 changes: 5 additions & 5 deletions lib/rasp/ast/expression.rb
Original file line number Diff line number Diff line change
Expand Up @@ -25,17 +25,17 @@ class EqvOp < BinaryOp
end
class XorOp < BinaryOp
def op_bytecode(g)
g.send :^
g.send :^, 1
end
end
class OrOp < BinaryOp
def op_bytecode(g)
g.send :|
g.send :|, 1
end
end
class AndOp < BinaryOp
def op_bytecode(g)
g.send :&
g.send :&, 1
end
end
class NotOp < UnaryOp
Expand All @@ -47,7 +47,7 @@ def initialize(operator, lhs, rhs)
@operator = operator
end
def op_bytecode(g)
g.send @operator.to_sym
g.send @operator.to_sym, 1
end
end
class StringAppend < BinaryOp
Expand All @@ -63,7 +63,7 @@ def initialize(operator, lhs, rhs)
@operator = operator
end
def op_bytecode(g)
g.send @operator.to_sym
g.send @operator.to_sym, 1
end
end
class UnaryPlus < UnaryOp
Expand Down
57 changes: 39 additions & 18 deletions lib/rasp/ast/flow.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@ def bytecode(g)
top = g.new_label
top.set!

@body.bytecode(g)
@body.each do |s|
s.bytecode(g)
end
g.goto top
end
end
Expand Down Expand Up @@ -57,24 +59,35 @@ def initialize(var, start, finish, step, body)
@var, @start, @finish, @step = var, start, finish, step
end
def bytecode(g)
# TODO
# FIXME
if g.state.scope.variables.key? var
loop_var = g.state.scope.variable(var).reference
else
loop_var = g.state.scope.global.variable(var).reference
end

finish_var = Rubinius::Compiler::LocalVariable.new(g.state.scope.allocate_slot).reference
@finish.bytecode(g)
@step.bytecode(g) if @step
finish_var.set_bytecode(g)

unless Rasp::AST::Literal === @step || @step.nil?
step_var = Rubinius::Compiler::LocalVariable.new(g.state.scope.allocate_slot).reference
dir_var = Rubinius::Compiler::LocalVariable.new(g.state.scope.allocate_slot).reference

@step.bytecode(g) if @step
g.dup
step_var.set_bytecode(g)
g.meta_push_0
g.send_stack :<, 1
dir_var.set_bytecode(g)
end

@start.bytecode(g)
loop_var.set_bytecode(g)

loop_body = g.new_label
loop_body.set!

@body.each do |s|
#s.bytecode(g)
end
Expand All @@ -83,16 +96,17 @@ def bytecode(g)
# Step is constant

if @step
g.dup_many 2 # @step, @finish, ...
@step.bytecode(g)
loop_var.get_bytecode(g)
g.send_stack :+, 1
else
g.dup # @finish, ...
loop_var.get_bytecode(g)
g.send_vcall :inc
end
g.dup
loop_var.set_bytecode(g)
finish_var.get_bytecode(g)
g.swap

if @step.nil? || @step.value > 0
# Always working forwards
Expand All @@ -107,11 +121,7 @@ def bytecode(g)

g.gif loop_body

if @step
g.pop_many 2
else
g.pop
end
# finish_var is done now; can we get rid of it?
else
raise "dynstep!"
# Dynamic step; have to work out which way we're going at runtime
Expand All @@ -127,13 +137,16 @@ def bytecode(g)
check_backwards = g.new_label
end_loop = g.new_label

g.dup_many 3 # loop_backwards, @step, @finish, ...
finish_var.get_bytecode(g)
step_var.get_bytecode(g)
loop_var.get_bytecode(g)
g.send_stack :+, 1
g.dup
loop_var.set_bytecode(g)

dir_var.get_bytecode(g)
g.git check_backwards

g.send_stack :>, 1
g.gif loop_body
g.goto end_loop
Expand All @@ -143,7 +156,6 @@ def bytecode(g)
g.gif loop_body

end_loop.set!
g.pop_many 3
end
end
end
Expand All @@ -165,19 +177,28 @@ def initialize(condition, true_body, false_body)
end

def bytecode(g)
done = g.new_label
false_label = g.new_label

@condition.bytecode(g)
g.giz false_label

@true_body.bytecode(g)
g.goto done
@true_body.each do |s|
s.bytecode(g)
end

false_label.set!
@false_body.bytecode(g)
if @false_body && @false_body.size > 0
done = g.new_label
g.goto done

done.set!
false_label.set!
@false_body.each do |s|
s.bytecode(g)
end

done.set!
else
false_label.set!
end
end
end

Expand Down
21 changes: 16 additions & 5 deletions lib/rasp/ast/simple.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,20 @@ module Rasp::AST
class Statement < Node
end
class Assignment < Statement
attr_accessor :var, :value
def initialize(var, value)
@var, @value = var, value
attr_accessor :var, :newval
def initialize(var, newval)
@var, @newval = var, newval
end
def bytecode(g)
if g.state.scope.variables.key? var
ref = g.state.scope.variable(var).reference
else
ref = g.state.scope.global.variable(var).reference
end

@newval.bytecode(g)
ref.set_bytecode(g)
g.pop
end
end
class SetAssignment < Assignment
Expand All @@ -16,8 +27,8 @@ def bytecode(g)
raise "Duplicate constant: #@var"
end

# @value is syntactically guaranteed to be a Literal.
g.constants[@var] = @value.value
# @newval is syntactically guaranteed to be a Literal.
g.constants[@var] = @newval.value
end
end
class Declaration < Statement
Expand Down
11 changes: 7 additions & 4 deletions lib/rasp/compiler.rb
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@ def compile(ast, filename="(rasp)", line_number=1)
g.ret
g.close

g.local_count = ast.local_count
g.local_names = ast.local_names

g.encode
cm = g.package ::Rubinius::CompiledMethod
puts cm.decode if $DEBUG
Expand All @@ -59,20 +62,20 @@ def initialize
end

def giz(label)
dup_top
dup
gif label

meta_push_0
meta_send_op_eq find_literal(:==)
meta_send_op_equal find_literal(:==)
git label
end
def gnz(label)
f = new_label
dup_top
dup
gif f # if it's false, don't compare to zero; just continue

meta_push_0
meta_send_op_eq find_literal(:==)
meta_send_op_equal find_literal(:==)
gif label

f.set!
Expand Down
16 changes: 10 additions & 6 deletions lib/rasp/parser.citrus
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ grammar Rasp::Parser
`for` SP `each` SP identifier SP `in` SP expression ENDSTATEMENT statement* `next` ENDSTATEMENT
end
rule do_loop
(`do` ENDSTATEMENT statement* `loop` ENDSTATEMENT
((`do` ENDSTATEMENT body:statement* `loop` ENDSTATEMENT) { Rasp::AST::Loop.new :do, body.matches.map {|m| m.value }.compact }
|`do` SP (`while` | `until`) SP expression ENDSTATEMENT statement* `loop` ENDSTATEMENT
|`do` ENDSTATEMENT statement* `loop` SP (`while` | `until`) SP expression ENDSTATEMENT
|`while` SP expression ENDSTATEMENT statement* `wend` ENDSTATEMENT
Expand All @@ -80,7 +80,11 @@ grammar Rasp::Parser
{ Rasp::AST::ForLoop.new(identifier.value, start.value, finish.value, first(:step) && first(:step).value, body.matches.map {|m| m.value }) }
end
rule single_line_if
`if` SP expression SP `then` SP (single_line_if | simple_statement_chain (SP `else` SP (single_line_if | simple_statement_chain EOL) | EOL) )
(`if` SP expression SP `then` SP truepart:(single:single_line_if { [single] } | list:simple_statement_chain) (SP `else` SP falsepart:(single:single_line_if | list:simple_statement_chain EOL) | EOL) )
{
false_list = first(:falsepart) && (falsepart.first(:single) ? [falsepart.single.value] : falsepart.list.value)
Rasp::AST::If.new(expression.value, truepart.value, false_list)
}
end
rule full_if_block
`if` SP expression SP `then` ENDSTATEMENT statement*
Expand All @@ -89,7 +93,7 @@ grammar Rasp::Parser
`end` SP `if` ENDSTATEMENT
end
rule simple_statement_chain
(simple_statement SP? ":" SP?)* simple_statement
((simple_statement SP? ":" SP?)* simple_statement) { find(:simple_statement).map {|s| s.value } }
end
rule simple_statement
(assignment
Expand All @@ -108,10 +112,10 @@ grammar Rasp::Parser
| (`on` SP `error` SP `goto` SP "0") { Rasp::AST::ErrorControl.new(false) }
end
rule exit_statement
(`exit` SP type:(`sub` | `function` | `property` | `do` | `for`)) { Rasp::AST::ExitStatement.new type.downcase.to_sym }
(`exit` SP extype:(`sub` | `function` | `property` | `do` | `for`)) { Rasp::AST::ExitStatement.new extype.downcase.to_sym }
end
rule assignment
(objvalue SP? "=" SP? expression
((objvalue SP? "=" SP? expression) { Rasp::AST::Assignment.new(objvalue.value.name, expression.value) }
|`set` SP objvalue SP? "=" SP? expression
)
end
Expand Down Expand Up @@ -266,7 +270,7 @@ grammar Rasp::Parser
/[+-]?[0-9]+/ { Rasp::AST::Integer.new to_i }
end
rule float
/[0-9]+.[0-9]+/ { Rasp::AST::Float.new to_f }
/[0-9]+\.[0-9]+/ { Rasp::AST::Float.new to_f }
end
rule string
/"([^"]|"")*"/ { Rasp::AST::String.new to_s }
Expand Down

0 comments on commit d21fcee

Please sign in to comment.