From 18935366feb1410c69e25ebfd5ec3acc6d16948d Mon Sep 17 00:00:00 2001 From: Torsten Ruger Date: Sun, 27 Sep 2015 14:30:41 +0300 Subject: [PATCH] introducing class variable and typed arguments --- lib/bosl/compiler/function_expression.rb | 2 +- lib/parfait.rb | 1 + lib/parfait/method.rb | 17 ++++++++++------- lib/parfait/module.rb | 4 ++-- lib/parfait/variable.rb | 9 +++++++++ lib/register/builtin/integer.rb | 2 +- lib/virtual/boot.rb | 3 ++- lib/virtual/method_source.rb | 14 +++++++++++--- 8 files changed, 37 insertions(+), 15 deletions(-) create mode 100644 lib/parfait/variable.rb diff --git a/lib/bosl/compiler/function_expression.rb b/lib/bosl/compiler/function_expression.rb index 18dfc83c..fcaf9fa3 100644 --- a/lib/bosl/compiler/function_expression.rb +++ b/lib/bosl/compiler/function_expression.rb @@ -7,7 +7,7 @@ module Bosl name = name.to_a.first args = parameters.to_a.collect do |p| raise "error, argument must be a identifier, not #{p}" unless p.type == :parameter - p[2] + Parfait::Variable.new( p.first , p[1]) end if receiver diff --git a/lib/parfait.rb b/lib/parfait.rb index 456e68e5..fd95c6ca 100644 --- a/lib/parfait.rb +++ b/lib/parfait.rb @@ -8,6 +8,7 @@ require "parfait/list" require "parfait/word" require "parfait/binary_code" require "parfait/method" +require "parfait/variable" require "parfait/dictionary" require "parfait/layout" require "parfait/message" diff --git a/lib/parfait/method.rb b/lib/parfait/method.rb index 346c0729..46a6c443 100644 --- a/lib/parfait/method.rb +++ b/lib/parfait/method.rb @@ -9,7 +9,7 @@ module Parfait # static description of a method # name - # arg_names + # arguments # known local variable names # executable code @@ -18,17 +18,20 @@ module Parfait class Method < Object - def initialize clazz , name , arg_names + def initialize clazz , name , arguments super() raise "No class #{name}" unless clazz self.for_class = clazz self.name = name self.code = BinaryCode.new name - raise "Wrong type, expect List not #{arg_names.class}" unless arg_names.is_a? List - self.arg_names = arg_names + raise "Wrong type, expect List not #{arguments.class}" unless arguments.is_a? List + arguments.each do |var| + raise "Must be variable argument, not #{var}" unless var.is_a? Variable + end + self.arguments = arguments self.locals = List.new end - attributes [:name , :arg_names , :for_class , :code , :locals ] + attributes [:name , :arguments , :for_class , :code , :locals ] # determine whether this method has a variable by the given name @@ -45,7 +48,7 @@ module Parfait # determine whether this method has an argument by the name def has_arg name raise "has_arg #{name}.#{name.class}" unless name.is_a? Symbol - self.arg_names.index_of name + self.arguments.index_of name end # determine if method has a local variable or tmp (anonymous local) by given name @@ -64,7 +67,7 @@ module Parfait def get_var name var = has_var name - raise "no var #{name} in method #{self.name} , #{self.locals} #{self.arg_names}" unless var + raise "no var #{name} in method #{self.name} , #{self.locals} #{self.arguments}" unless var var end diff --git a/lib/parfait/module.rb b/lib/parfait/module.rb index a3ad6472..39d86ae8 100644 --- a/lib/parfait/module.rb +++ b/lib/parfait/module.rb @@ -58,12 +58,12 @@ module Parfait self.instance_methods.delete found end - def create_instance_method method_name , arg_names + def create_instance_method method_name , arguments raise "create_instance_method #{method_name}.#{method_name.class}" unless method_name.is_a?(Symbol) clazz = object_layout().object_class() raise "??? #{method_name}" unless clazz #puts "Self: #{self.class} clazz: #{clazz.name}" - Method.new( clazz , method_name , arg_names ) + Method.new( clazz , method_name , arguments ) end # this needs to be done during booting as we can't have all the classes and superclassses diff --git a/lib/parfait/variable.rb b/lib/parfait/variable.rb new file mode 100644 index 00000000..a66c0913 --- /dev/null +++ b/lib/parfait/variable.rb @@ -0,0 +1,9 @@ +module Parfait + class Variable < Object + def initialize type , name , value = nil + @type , @name , @value = type , name , value + @value = 0 if @type == :int and value == nil + end + attributes [:type , :name, :value] + end +end diff --git a/lib/register/builtin/integer.rb b/lib/register/builtin/integer.rb index 2943efec..d508db24 100644 --- a/lib/register/builtin/integer.rb +++ b/lib/register/builtin/integer.rb @@ -4,7 +4,7 @@ module Register module Integer module ClassMethods def plus c - plus_function = Virtual::MethodSource.create_method(:Integer,:int,:plus , [:Integer] ) + plus_function = Virtual::MethodSource.create_method(:Integer,:int,:plus , [:int] ) plus_function.source.return_type = Virtual::Integer plus_function.source.receiver = Virtual::Integer diff --git a/lib/virtual/boot.rb b/lib/virtual/boot.rb index 87aa00d2..bae4a017 100644 --- a/lib/virtual/boot.rb +++ b/lib/virtual/boot.rb @@ -130,7 +130,8 @@ module Virtual # instances are copied (shame on you) :Class => [:object_layout , :name , :instance_methods , :super_class , :meta_class], :Dictionary => [:keys , :values ] , - :Method => [:name , :code ,:arg_names , :for_class, :locals ] , + :Method => [:name , :code ,:arguments , :for_class, :locals ] , + :Variable => [:type , :name , :value ] , :Module => [:name , :instance_methods , :super_class , :meta_class ] } end diff --git a/lib/virtual/method_source.rb b/lib/virtual/method_source.rb index 4d5a3a53..9e6976c4 100644 --- a/lib/virtual/method_source.rb +++ b/lib/virtual/method_source.rb @@ -38,7 +38,15 @@ module Virtual clazz = Virtual.machine.space.get_class_by_name class_name raise "No such class #{class_name}" unless clazz return_type = Virtual::Type.from_sym return_type - method = clazz.create_instance_method( method_name , Virtual.new_list(args)) + arguemnts = [] + args.each_with_index do | arg , index | + unless arg.is_a? Parfait::Variable + raise "not type #{arg}:#{arg.class}" unless arg == :int || arg == :ref + arg = Parfait::Variable.new arg , "arg#{index}".to_sym + end + arguemnts << arg + end + method = clazz.create_instance_method( method_name , Virtual.new_list(arguemnts)) method.source = MethodSource.new(method , return_type) method end @@ -125,8 +133,8 @@ module Virtual # mov and add will be called on Machine and generate Instructions that are then added # to the current block # also symbols are supported and wrapped as register usages (for bare metal programming) -# def method_missing(meth, *arg_names, &block) -# add_code ::Arm::ArmMachine.send(meth , *arg_names) +# def method_missing(meth, *arguments, &block) +# add_code ::Arm::ArmMachine.send(meth , *arguments) # end def byte_length