From 0813312ddc8222e8db3f889c394b61e2eb29250b Mon Sep 17 00:00:00 2001 From: Torsten Ruger Date: Sun, 18 Mar 2018 22:08:35 +0530 Subject: [PATCH] using compiler_for to create all building compilers unify api, create defaults and especially pass the right types into the typed method creation --- lib/risc/builtin/compile_helper.rb | 7 ++++--- lib/risc/builtin/integer.rb | 7 ++++--- lib/risc/builtin/kernel.rb | 6 ++++-- lib/risc/builtin/object.rb | 6 ++---- lib/risc/builtin/space.rb | 4 +++- lib/risc/builtin/word.rb | 12 +++++------- lib/risc/method_compiler.rb | 10 +++++----- 7 files changed, 27 insertions(+), 25 deletions(-) diff --git a/lib/risc/builtin/compile_helper.rb b/lib/risc/builtin/compile_helper.rb index 35252c1d..b20707c5 100644 --- a/lib/risc/builtin/compile_helper.rb +++ b/lib/risc/builtin/compile_helper.rb @@ -9,9 +9,10 @@ module Risc return me , int_arg end - def compiler_for( type , method_name , extra_args = {}) - args = {:index => :Integer}.merge( extra_args ) - Risc::MethodCompiler.create_method(type , method_name , args ).init_method + def compiler_for( type , method_name , arguments , locals = {}) + frame = Parfait::NamedList.type_for( locals ) #TODO fix locals passing/ using in builtin + args = Parfait::NamedList.type_for( arguments ) + Risc::MethodCompiler.create_method(type , method_name , args, frame ).init_method end # Load the value diff --git a/lib/risc/builtin/integer.rb b/lib/risc/builtin/integer.rb index 2e019356..44501b6c 100644 --- a/lib/risc/builtin/integer.rb +++ b/lib/risc/builtin/integer.rb @@ -4,20 +4,21 @@ module Risc module Integer module ClassMethods include AST::Sexp + include CompileHelper def mod4 context - compiler = Risc::MethodCompiler.create_method(:Integer,:mod4 ).init_method + compiler = compiler_for(:Integer,:mod4 ,{}) return compiler.method end def putint context - compiler = Risc::MethodCompiler.create_method(:Integer,:putint ).init_method + compiler = compiler_for(:Integer,:putint ,{}) return compiler.method end def div10 context s = "div_10" - compiler = Risc::MethodCompiler.create_method(:Integer,:div10 ).init_method + compiler = compiler_for(:Integer,:div10 ,{}) me = compiler.add_known( :receiver ) tmp = compiler.add_known( :receiver ) q = compiler.add_known( :receiver ) diff --git a/lib/risc/builtin/kernel.rb b/lib/risc/builtin/kernel.rb index 6b5ae4ee..a7248d43 100644 --- a/lib/risc/builtin/kernel.rb +++ b/lib/risc/builtin/kernel.rb @@ -2,11 +2,13 @@ module Risc module Builtin module Kernel module ClassMethods + include CompileHelper # this is the really really first place the machine starts (apart from the jump here) # it isn't really a function, ie it is jumped to (not called), exits and may not return # so it is responsible for initial setup def __init__ context - compiler = Risc::MethodCompiler.create_method(:Kernel,:__init__ ) + compiler = Risc::MethodCompiler.create_method(:Kernel,:__init__ , + Parfait::NamedList.type_for({}) , Parfait::NamedList.type_for({})) new_start = Risc.label("__init__ start" , "__init__" ) compiler.method.set_instructions( new_start) compiler.set_current new_start @@ -29,7 +31,7 @@ module Risc end def exit context - compiler = Risc::MethodCompiler.create_method(:Kernel,:exit ).init_method + compiler = compiler_for(:Kernel,:exit ,{}) emit_syscall( compiler , :exit ) return compiler.method end diff --git a/lib/risc/builtin/object.rb b/lib/risc/builtin/object.rb index de058c81..9d0c206f 100644 --- a/lib/risc/builtin/object.rb +++ b/lib/risc/builtin/object.rb @@ -1,5 +1,3 @@ -require_relative "compile_helper" - module Risc module Builtin class Object @@ -10,7 +8,7 @@ module Risc # return is stored in return_value # (this method returns a new method off course, like all builtin) def get_internal_word context - compiler = compiler_for(:Object , :get_internal_word ) + compiler = compiler_for(:Object , :get_internal_word ,{at: :Integer}) source = "get_internal_word" me , index = self_and_int_arg(compiler,source) # reduce me to me[index] @@ -23,7 +21,7 @@ module Risc # self[index] = val basically. Index is the first arg , value the second # no return def set_internal_word context - compiler = compiler_for(:Object , :set_internal_word , {:value => :Object} ) + compiler = compiler_for(:Object , :set_internal_word , {at: :Integer, :value => :Object} ) source = "set_internal_word" me , index = self_and_int_arg(compiler,source) value = load_int_arg_at(compiler,source , 2) diff --git a/lib/risc/builtin/space.rb b/lib/risc/builtin/space.rb index 5ec567d3..10a7fdb2 100644 --- a/lib/risc/builtin/space.rb +++ b/lib/risc/builtin/space.rb @@ -1,15 +1,17 @@ require "ast/sexp" +require_relative "compile_helper" module Risc module Builtin class Space module ClassMethods include AST::Sexp + include CompileHelper # main entry point, ie __init__ calls this # defined here as empty, to be redefined def main context - compiler = Risc::MethodCompiler.create_method(:Space , :main ).init_method + compiler = compiler_for(:Space , :main ,{args: :Integer}) return compiler.method end diff --git a/lib/risc/builtin/word.rb b/lib/risc/builtin/word.rb index 49819b36..6dc140f9 100644 --- a/lib/risc/builtin/word.rb +++ b/lib/risc/builtin/word.rb @@ -1,5 +1,3 @@ -require_relative "compile_helper" - module Risc module Builtin module Word @@ -7,7 +5,7 @@ module Risc include CompileHelper def putstring context - compiler = Risc::MethodCompiler.create_method(:Word , :putstring ).init_method + compiler = compiler_for(:Word , :putstring ,{}) compiler.add_slot_to_reg( "putstring" , :message , :receiver , :new_message ) index = Parfait::Word.get_length_index reg = RiscValue.new(:r2 , :Integer) @@ -19,7 +17,7 @@ module Risc # self[index] basically. Index is the first arg > 0 # return (and word sized int) is stored in return_value def get_internal_byte context - compiler = compiler_for(:Word , :get_internal_byte) + compiler = compiler_for(:Word , :get_internal_byte , {at: :Integer}) source = "get_internal_byte" me , index = self_and_int_arg(compiler,source) # reduce me to me[index] @@ -33,7 +31,7 @@ module Risc # value the second # no return def set_internal_byte context - compiler = compiler_for(:Word, :set_internal_byte , {:value => :Integer} ) + compiler = compiler_for(:Word, :set_internal_byte , {at: :Integer , :value => :Integer} ) args = compiler.method.arguments len = args.instance_length raise "Compiler arg number mismatch, method=#{args} " if len != 3 @@ -46,7 +44,7 @@ module Risc end # resolve the method name of self, on the given object - # may seem wrong way around at first sight, but we know the type of string And + # may seem wrong way around at first sight, but we know the type of string. And # thus resolving this method happens at compile time, whereas any method on an # unknown self (the object given) needs resolving and that is just what we are doing # ( ie the snake bites it's tail) @@ -56,7 +54,7 @@ module Risc compiler = compiler_for(:Word, :resolve_method , {:value => :Object} ) args = compiler.method.arguments len = args.instance_length - raise "Compiler arg number mismatch, method=#{args} " if len != 3 + raise "Compiler arg number mismatch, method=#{args} " if len != 2 return compiler.method end diff --git a/lib/risc/method_compiler.rb b/lib/risc/method_compiler.rb index 128aa987..fcfa2d92 100644 --- a/lib/risc/method_compiler.rb +++ b/lib/risc/method_compiler.rb @@ -22,10 +22,10 @@ module Risc # create the method, do some checks and set it as the current method to be added to # class_name and method_name are pretty clear, args are given as a ruby array - def self.create_method( class_name , method_name , args = {}) + def self.create_method( class_name , method_name , args , frame ) raise "create_method #{class_name}.#{class_name.class}" unless class_name.is_a? Symbol clazz = Parfait.object_space.get_class_by_name! class_name - create_method_for( clazz.instance_type , method_name , args) + create_method_for( clazz.instance_type , method_name , args , frame) end # create a method for the given type ( Parfait type object) @@ -33,11 +33,11 @@ module Risc # args a hash that will be converted to a type # the created method is set as the current and the given type too # return the compiler (for chaining) - def self.create_method_for( type , method_name , args ) + def self.create_method_for( type , method_name , args , frame) raise "create_method #{type.inspect} is not a Type" unless type.is_a? Parfait::Type - raise "Args must be Hash #{args}" unless args.is_a?(Hash) + raise "Args must be Type #{args}" unless args.is_a?(Parfait::Type) raise "create_method #{method_name}.#{method_name.class}" unless method_name.is_a? Symbol - method = type.create_method( method_name , args) + method = type.create_method( method_name , args , frame) self.new(method) end