brainstorming mode on the new way (tm)
This commit is contained in:
parent
ee5615ec03
commit
c505db490f
@ -14,11 +14,13 @@ module Ast
|
||||
Virtual::TrueValue.new
|
||||
end
|
||||
end
|
||||
|
||||
class FalseExpression
|
||||
def compile frame
|
||||
Virtual::FalseValue.new
|
||||
end
|
||||
end
|
||||
|
||||
class NilExpression
|
||||
def compile frame
|
||||
Virtual::NilValue.new
|
||||
@ -28,9 +30,15 @@ module Ast
|
||||
class NameExpression < Expression
|
||||
# attr_reader :name
|
||||
|
||||
# compiling a variable resolves it. If it's not defined look call it as a menthod (which may raise NoMethodFound)
|
||||
def compile frame
|
||||
frame.get(name)
|
||||
# compiling name needs to check if it's a variable and if so resolve it
|
||||
# otherwise it's a method without args and a send is ussued.
|
||||
# this makes the namespace static, ie when eval and co are implemented method needs recompilation
|
||||
def compile frame , method
|
||||
if method.has_var(name)
|
||||
frame.compile_get(name , method )
|
||||
else
|
||||
frame.compile_send( name , method )
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -1,8 +1,8 @@
|
||||
module Ast
|
||||
class ExpressionList < Expression
|
||||
# attr_reader :expressions
|
||||
def compile binding
|
||||
expressions.collect { |part| part.compile( binding ) }
|
||||
def compile binding , method
|
||||
expressions.collect { |part| part.compile( binding , method ) }
|
||||
end
|
||||
end
|
||||
end
|
@ -22,5 +22,14 @@ module Virtual
|
||||
@binding = List.new
|
||||
end
|
||||
attr_reader :next_normal, :next_exception, :me, :binding
|
||||
|
||||
#
|
||||
def compile_get name , method
|
||||
method.add FrameGet.new(name)
|
||||
end
|
||||
|
||||
def compile_send name , method
|
||||
method.add FrameSend.new(name)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -9,7 +9,11 @@ module Virtual
|
||||
|
||||
# This is partly because jumping over this layer and doing in straight in assember was too big a step
|
||||
class Instruction
|
||||
attr_accessor :next
|
||||
|
||||
def inspect
|
||||
self.class.name + ".new()"
|
||||
end
|
||||
end
|
||||
|
||||
# the first instruction we need is to stop. Off course in a real machine this would be a syscall, but that is just
|
||||
@ -19,4 +23,30 @@ module Virtual
|
||||
class Halt < Instruction
|
||||
|
||||
end
|
||||
|
||||
# following classes are stubs. currently in brainstorming mode, so anything may change anytime
|
||||
class MethodEnter < Instruction
|
||||
end
|
||||
|
||||
class FrameGet < Instruction
|
||||
def initialize name
|
||||
@name = name
|
||||
end
|
||||
end
|
||||
|
||||
class FrameSend < Instruction
|
||||
|
||||
def initialize name
|
||||
@name = name.to_sym
|
||||
end
|
||||
attr_reader :name
|
||||
|
||||
def == other
|
||||
self.class == other.class && self.name == other.name
|
||||
end
|
||||
def inspect
|
||||
self.class.name + ".new(:#{@name})"
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
@ -37,7 +37,7 @@ module Virtual
|
||||
end
|
||||
|
||||
def initialize
|
||||
the_end = HaltInstruction.new
|
||||
the_end = Halt.new
|
||||
@frame = Frame.new(the_end , the_end , :Object)
|
||||
end
|
||||
attr_reader :frame
|
||||
@ -51,15 +51,12 @@ module Virtual
|
||||
instruction = next_instruction
|
||||
end
|
||||
end
|
||||
#return an anonymous new function (the top level) into which code is compiled
|
||||
def anonymous
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
require_relative "list"
|
||||
require_relative "instruction"
|
||||
require_relative "method"
|
||||
require_relative "frame"
|
||||
require_relative "value"
|
||||
require_relative "mystery"
|
||||
|
38
lib/virtual/method.rb
Normal file
38
lib/virtual/method.rb
Normal file
@ -0,0 +1,38 @@
|
||||
module Virtual
|
||||
# static description of a method
|
||||
# name
|
||||
# args (with defaults)
|
||||
# code
|
||||
# return arg (usually mystery, but for coded ones can be more specific)
|
||||
# known local variable names
|
||||
# temp variables (numbered)
|
||||
#
|
||||
class Method
|
||||
#return the main function (the top level) into which code is compiled
|
||||
def Method.main
|
||||
Method.new(:main)
|
||||
end
|
||||
def initialize name , args = []
|
||||
@name = name
|
||||
@args = args
|
||||
@locals = []
|
||||
@start = MethodEnter.new
|
||||
@current = @start
|
||||
end
|
||||
attr_reader :name
|
||||
|
||||
def add instruction
|
||||
@current.next = instruction
|
||||
@current = instruction
|
||||
end
|
||||
|
||||
# determine whether this method has a variable by the given name
|
||||
# variables are locals and and arguments
|
||||
# used to determine if a send must be issued
|
||||
def has_var name
|
||||
var = @args.find {|a| a == name }
|
||||
var = @locals.find {|a| a == name } unless var
|
||||
var
|
||||
end
|
||||
end
|
||||
end
|
@ -28,7 +28,7 @@ class TestBasic < MiniTest::Test
|
||||
|
||||
def test_name
|
||||
@string_input = 'foo '
|
||||
@output = [nil]
|
||||
@output = [Virtual::FrameSend.new(:foo)]
|
||||
check
|
||||
end
|
||||
|
||||
|
@ -12,7 +12,7 @@ module VirtualHelper
|
||||
syntax = parser.parse_with_debug(@string_input)
|
||||
parts = Parser::Transform.new.apply(syntax)
|
||||
machine = Virtual::Machine.new
|
||||
expressions = parts.compile(machine.frame , machine.anonymous)
|
||||
expressions = parts.compile(machine.frame , Virtual::Method.main )
|
||||
assert_equal @output , expressions
|
||||
end
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user