2014-07-14 10:29:38 +02:00
|
|
|
require_relative "object"
|
2014-07-14 13:06:09 +02:00
|
|
|
|
2014-07-10 16:14:38 +02:00
|
|
|
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)
|
|
|
|
#
|
2014-07-14 10:29:38 +02:00
|
|
|
class Method < Virtual::Object
|
2014-07-10 16:14:38 +02:00
|
|
|
#return the main function (the top level) into which code is compiled
|
|
|
|
def Method.main
|
2014-07-14 13:06:09 +02:00
|
|
|
Method.new(:main , [] , Virtual::SelfReference )
|
2014-07-10 16:14:38 +02:00
|
|
|
end
|
2014-07-14 10:29:38 +02:00
|
|
|
def attributes
|
2014-07-14 15:19:47 +02:00
|
|
|
[:name , :args , :receiver , :return_type , :start]
|
2014-07-14 10:29:38 +02:00
|
|
|
end
|
2014-07-15 09:35:29 +02:00
|
|
|
def initialize name , args , receiver = Virtual::SelfReference.new , return_type = Virtual::Mystery , start = MethodEnter.new
|
2014-07-14 10:29:38 +02:00
|
|
|
@name = name.to_sym
|
2014-07-10 16:14:38 +02:00
|
|
|
@args = args
|
|
|
|
@locals = []
|
2014-07-14 23:00:00 +02:00
|
|
|
@tmps = []
|
2014-07-12 20:59:17 +02:00
|
|
|
@receiver = receiver
|
|
|
|
@return_type = return_type
|
2014-07-14 15:19:47 +02:00
|
|
|
@start = start
|
2014-07-10 16:14:38 +02:00
|
|
|
@current = @start
|
|
|
|
end
|
2014-07-14 13:29:33 +02:00
|
|
|
attr_reader :name , :args , :receiver , :start
|
|
|
|
attr_accessor :return_type
|
2014-07-10 16:14:38 +02:00
|
|
|
|
|
|
|
def add instruction
|
2014-07-14 23:00:00 +02:00
|
|
|
raise instruction.inspect unless instruction.is_a? Instruction
|
2014-07-10 16:14:38 +02:00
|
|
|
@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
|
2014-07-14 23:00:00 +02:00
|
|
|
var = @tmps.find {|a| a == name } unless var
|
2014-07-10 16:14:38 +02:00
|
|
|
var
|
|
|
|
end
|
2014-07-15 09:35:29 +02:00
|
|
|
alias :get_var :has_var
|
|
|
|
|
2014-07-14 23:00:00 +02:00
|
|
|
def get_tmp
|
|
|
|
name = "__tmp__#{@tmps.length}"
|
|
|
|
@tmps << name
|
|
|
|
Ast::NameExpression.new(name)
|
|
|
|
end
|
2014-07-10 16:14:38 +02:00
|
|
|
end
|
|
|
|
end
|