diff --git a/Gemfile.lock b/Gemfile.lock index 8ac2bb04..56e4e031 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -12,9 +12,9 @@ GIT GIT remote: git://github.com/salama/salama-reader.git - revision: 58b3553251bd23d2b666b25e23c8bc13ad87acdb + revision: 6bd5e9b5ee26e4e0157283e9af4389b13d660193 specs: - salama-reader (0.3.0) + salama-reader (0.4.0) ast (~> 2.1.0) parslet (~> 1.7.0) diff --git a/README.md b/README.md index 55550bde..f5866bf3 100644 --- a/README.md +++ b/README.md @@ -74,7 +74,7 @@ The full list is on the net and involves mostly just work. Parse Phisol, using Parslet. This has been separated out as it's own gem, [salama-reader](https://github.com/salama/salama-reader). Phisol is now fully typed (all variables, arguments and return). Also it has statements, unlike ruby -where everything is an expressions. Statements have no value. Otherwise it is quite basic, and +where everything is an statements. Statements have no value. Otherwise it is quite basic, and it's main purpose is to have an oo system language to compile to. I spent some time on the parse testing framework, so it is safe to fiddle and add. diff --git a/ToDo.md b/ToDo.md index 28fa244b..330dc31b 100644 --- a/ToDo.md +++ b/ToDo.md @@ -10,7 +10,7 @@ Some things that would be nice . . (if you did them :-) ) - utf8 support (string improvements generally) - SOF parser - more ruby grammar niceties. At the moment i am keeping it simple, so if there is a way around it - i won't implement it. Multi-assignments, all that chique where newline is used as expression demarcation + i won't implement it. Multi-assignments, all that chique where newline is used as statement demarcation Or the list of things i am not even planning of tackling at the moment diff --git a/lib/phisol/compiler.rb b/lib/phisol/compiler.rb index e1997881..743be14c 100644 --- a/lib/phisol/compiler.rb +++ b/lib/phisol/compiler.rb @@ -13,35 +13,35 @@ module Phisol # Some compile methods just add code, some may add structure (ie Blocks) while # others instantiate Class and Method objects # - # Everything in ruby is an expression, ie returns a value. So the effect of every compile + # Everything in ruby is an statement, ie returns a value. So the effect of every compile # is that a value is put into the ReturnSlot of the current Message. # The compile method (so every compile method) returns the value that it deposits. # # The process uses a visitor pattern (from AST::Processor) to dispatch according to the - # type the expression. So a s(:if xx) will become an on_if(node) call. + # type the statement. So a s(:if xx) will become an on_if(node) call. # This makes the dispatch extensible, ie Expressions may be added by external code, # as long as matching compile methods are supplied too. # - def self.compile expression + def self.compile statement compiler = Compiler.new - compiler.process expression + compiler.process statement end end end require_relative "ast_helper" -require_relative "compiler/basic_expressions" -require_relative "compiler/callsite_expression" +require_relative "compiler/basic_values" +require_relative "compiler/call_site" require_relative "compiler/class_field" -require_relative "compiler/compound_expressions" -require_relative "compiler/expression_list" +require_relative "compiler/collections" +require_relative "compiler/statement_list" require_relative "compiler/field_def" require_relative "compiler/field_access" -require_relative "compiler/function_expression" -require_relative "compiler/if_expression" -require_relative "compiler/module_expression" +require_relative "compiler/function_definition" +require_relative "compiler/if_statement" +require_relative "compiler/class_statement" require_relative "compiler/name_expression" -require_relative "compiler/operator_expressions" -require_relative "compiler/return_expression" -require_relative "compiler/while_expression" +require_relative "compiler/operator_value" +require_relative "compiler/return_statement" +require_relative "compiler/while_statement" diff --git a/lib/phisol/compiler/basic_expressions.rb b/lib/phisol/compiler/basic_values.rb similarity index 83% rename from lib/phisol/compiler/basic_expressions.rb rename to lib/phisol/compiler/basic_values.rb index 38595301..b7d90eb6 100644 --- a/lib/phisol/compiler/basic_expressions.rb +++ b/lib/phisol/compiler/basic_values.rb @@ -3,7 +3,7 @@ module Phisol Compiler.class_eval do - # Constant expressions can by definition be evaluated at compile time. + # Constant statements can by definition be evaluated at compile time. # But that does not solve their storage, ie they need to be accessible at runtime from _somewhere_ # So we view ConstantExpressions like functions that return the value of the constant. # In other words, their storage is the return slot as it would be for a method @@ -11,34 +11,34 @@ module Phisol # The current approach moves the constant into a variable before using it # But in the future (in the one that holds great things) we optimize those unneccesay moves away - def on_int expression - int = expression.first + def on_int statement + int = statement.first to = Virtual::Return.new(Virtual::Integer , int) @method.source.add_code Virtual::Set.new( int , to ) to end - def on_true expression + def on_true statement to = Virtual::Return.new(Virtual::Reference , true ) @method.source.add_code Virtual::Set.new( true , to ) to end - def on_false expression + def on_false statement to = Virtual::Return.new(Virtual::Reference , false) @method.source.add_code Virtual::Set.new( false , to ) to end - def on_nil expression + def on_nil statement to = Virtual::Return.new(Virtual::Reference , nil) @method.source.add_code Virtual::Set.new( nil , to ) to end - def on_string expression + def on_string statement # Clearly a TODO here to implement strings rather than reusing symbols - value = expression.first.to_sym + value = statement.first.to_sym to = Virtual::Return.new(Virtual::Reference , value) @method.source.constants << value @method.source.add_code Virtual::Set.new( value , to ) diff --git a/lib/phisol/compiler/callsite_expression.rb b/lib/phisol/compiler/call_site.rb similarity index 94% rename from lib/phisol/compiler/callsite_expression.rb rename to lib/phisol/compiler/call_site.rb index 3eb10ad7..64e3b5af 100644 --- a/lib/phisol/compiler/callsite_expression.rb +++ b/lib/phisol/compiler/call_site.rb @@ -1,8 +1,8 @@ module Phisol Compiler.class_eval do - def on_call expression - name , arguments , receiver = *expression + def on_call statement + name , arguments , receiver = *statement name = name.to_a.first raise "not inside method " unless @method if receiver @@ -65,7 +65,7 @@ module Phisol end raise "Method not implemented #{me.value}.#{name}" unless method # the effect of the method is that the NewMessage Return slot will be filled, return it - # (this is what is moved _inside_ above loop for such expressions that are calls (or constants)) + # (this is what is moved _inside_ above loop for such statements that are calls (or constants)) Virtual::Return.new( method.source.return_type ) end end diff --git a/lib/phisol/compiler/class_field.rb b/lib/phisol/compiler/class_field.rb index 1f3d0e88..6ed86f6d 100644 --- a/lib/phisol/compiler/class_field.rb +++ b/lib/phisol/compiler/class_field.rb @@ -1,9 +1,9 @@ module Phisol Compiler.class_eval do - def on_class_field expression - #puts expression.inspect - type , name , value = *expression + def on_class_field statement + #puts statement.inspect + type , name , value = *statement for_class = @clazz raise "no class" unless for_class diff --git a/lib/phisol/compiler/class_statement.rb b/lib/phisol/compiler/class_statement.rb new file mode 100644 index 00000000..eecc3bc4 --- /dev/null +++ b/lib/phisol/compiler/class_statement.rb @@ -0,0 +1,15 @@ +module Phisol + Compiler.class_eval do + + def on_class statement + #puts statement.inspect + name , derives , statements = *statement + raise "classes dont yet play babushka, get coding #{name}" if @clazz + @clazz = Parfait::Space.object_space.get_class_by_name! name + puts "Compiling class #{@clazz.name.inspect}" + statement_value = process_all(statements).last + @clazz = nil + return statement_value + end + end +end diff --git a/lib/phisol/compiler/compound_expressions.rb b/lib/phisol/compiler/collections.rb similarity index 83% rename from lib/phisol/compiler/compound_expressions.rb rename to lib/phisol/compiler/collections.rb index cfc69ac8..8f3a5075 100644 --- a/lib/phisol/compiler/compound_expressions.rb +++ b/lib/phisol/compiler/collections.rb @@ -2,7 +2,7 @@ module Phisol Compiler.class_eval do # attr_reader :values - def on_array expession, context + def on_array statement, context end # attr_reader :key , :value def on_association context diff --git a/lib/phisol/compiler/expression_list.rb b/lib/phisol/compiler/expression_list.rb deleted file mode 100644 index 4058d748..00000000 --- a/lib/phisol/compiler/expression_list.rb +++ /dev/null @@ -1,8 +0,0 @@ -module Phisol - Compiler.class_eval do -# list - attr_reader :expressions - def on_expressions expession - process_all( expession.children ) - end - end -end diff --git a/lib/phisol/compiler/field_access.rb b/lib/phisol/compiler/field_access.rb index d09d9b8b..9a36fd49 100644 --- a/lib/phisol/compiler/field_access.rb +++ b/lib/phisol/compiler/field_access.rb @@ -1,9 +1,9 @@ module Phisol Compiler.class_eval do - def on_field_access expression - #puts expression.inspect - receiver_ast , field_ast = *expression + def on_field_access statement + #puts statement.inspect + receiver_ast , field_ast = *statement receiver = receiver_ast.first_from(:name) field_name = field_ast.first_from(:name) diff --git a/lib/phisol/compiler/field_def.rb b/lib/phisol/compiler/field_def.rb index 7508c6a1..6fa5aa40 100644 --- a/lib/phisol/compiler/field_def.rb +++ b/lib/phisol/compiler/field_def.rb @@ -1,9 +1,9 @@ module Phisol Compiler.class_eval do - def on_field_def expression - #puts expression.inspect - type , name , value = *expression + def on_field_def statement + #puts statement.inspect + type , name , value = *statement index = @method.ensure_local( name , type ) diff --git a/lib/phisol/compiler/function_expression.rb b/lib/phisol/compiler/function_definition.rb similarity index 92% rename from lib/phisol/compiler/function_expression.rb rename to lib/phisol/compiler/function_definition.rb index cce3f430..c42f3b9d 100644 --- a/lib/phisol/compiler/function_expression.rb +++ b/lib/phisol/compiler/function_definition.rb @@ -1,9 +1,9 @@ module Phisol Compiler.class_eval do - def on_function expression - #puts expression.inspect - return_type , name , parameters, kids , receiver = *expression + def on_function statement + #puts statement.inspect + return_type , name , parameters, kids , receiver = *statement 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 diff --git a/lib/phisol/compiler/if_expression.rb b/lib/phisol/compiler/if_statement.rb similarity index 89% rename from lib/phisol/compiler/if_expression.rb rename to lib/phisol/compiler/if_statement.rb index 8df22405..0443f3e1 100644 --- a/lib/phisol/compiler/if_expression.rb +++ b/lib/phisol/compiler/if_statement.rb @@ -2,8 +2,8 @@ module Phisol Compiler.class_eval do # if - attr_reader :cond, :if_true, :if_false - def on_if expression - condition , if_true , if_false = *expression + def on_if statement + condition , if_true , if_false = *statement condition = condition.first # to execute the logic as the if states it, the blocks are the other way around # so we can the jump over the else if true , @@ -25,7 +25,7 @@ module Phisol # compile the false block @method.source.current false_block last = process_all(if_false).last if if_false - @method.source.add_code Register::AlwaysBranch.new(expression, merge_block ) + @method.source.add_code Register::AlwaysBranch.new(statement, merge_block ) #puts "compiled if: end" @method.source.current merge_block diff --git a/lib/phisol/compiler/module_expression.rb b/lib/phisol/compiler/module_expression.rb deleted file mode 100644 index aa30e6f6..00000000 --- a/lib/phisol/compiler/module_expression.rb +++ /dev/null @@ -1,20 +0,0 @@ -module Phisol - Compiler.class_eval do -# module attr_reader :name ,:expressions - def on_module expression - name , rest = *expression - return process_all(rest).last - end - - def on_class expression - #puts expression.inspect - name , derives , expressions = *expression - raise "classes dont yet play babushka, get coding #{name}" if @clazz - @clazz = Parfait::Space.object_space.get_class_by_name! name - puts "Compiling class #{@clazz.name.inspect}" - expression_value = process_all(expressions).last - @clazz = nil - return expression_value - end - end -end diff --git a/lib/phisol/compiler/name_expression.rb b/lib/phisol/compiler/name_expression.rb index d2e17cd9..5cc57b4e 100644 --- a/lib/phisol/compiler/name_expression.rb +++ b/lib/phisol/compiler/name_expression.rb @@ -5,8 +5,8 @@ module Phisol # 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 issued. # whichever way this goes the result is stored in the return slot (as all compiles) - def on_name expression - name = expression.to_a.first + def on_name statement + name = statement.to_a.first return Virtual::Self.new( Virtual::Reference.new(@clazz)) if name == :self # either an argument, so it's stored in message if( index = @method.has_arg(name)) diff --git a/lib/phisol/compiler/operator_expressions.rb b/lib/phisol/compiler/operator_value.rb similarity index 71% rename from lib/phisol/compiler/operator_expressions.rb rename to lib/phisol/compiler/operator_value.rb index b0529efe..26db036a 100644 --- a/lib/phisol/compiler/operator_expressions.rb +++ b/lib/phisol/compiler/operator_value.rb @@ -1,30 +1,30 @@ module Phisol Compiler.class_eval do - def on_operator expression - puts "operator #{expression.inspect}" - operator , left_e , right_e = *expression + def on_operator statement + puts "operator #{statement.inspect}" + operator , left_e , right_e = *statement left_slot = process(left_e) right_slot = process(right_e) puts "left #{left_slot}" puts "right #{right_slot}" tmp1 = Register.tmp_reg tmp2 = tmp1.next_reg_use - get = Register.get_slot_to(expression , left_slot , tmp1 ) - get2 = Register.get_slot_to(expression , right_slot , tmp2 ) + get = Register.get_slot_to(statement , left_slot , tmp1 ) + get2 = Register.get_slot_to(statement , right_slot , tmp2 ) puts "GET #{get}" puts "GET2 #{get2}" @method.source.add_code get @method.source.add_code get2 - @method.source.add_code Register::OperatorInstruction.new(expression,operator, tmp1,tmp2) + @method.source.add_code Register::OperatorInstruction.new(statement,operator, tmp1,tmp2) Virtual::Return.new(:int ) end - def on_assign expression - puts expression.inspect - name , value = *expression + def on_assign statement + puts statement.inspect + name , value = *statement name = name.to_a.first v = process(value) index = @method.has_local( name ) diff --git a/lib/phisol/compiler/return_expression.rb b/lib/phisol/compiler/return_expression.rb deleted file mode 100644 index 03d7fa54..00000000 --- a/lib/phisol/compiler/return_expression.rb +++ /dev/null @@ -1,9 +0,0 @@ -module Phisol - Compiler.class_eval do - -# return attr_reader :expression - def on_return expression - return process(expression.to_a.first ) - end - end -end diff --git a/lib/phisol/compiler/return_statement.rb b/lib/phisol/compiler/return_statement.rb new file mode 100644 index 00000000..53548ff0 --- /dev/null +++ b/lib/phisol/compiler/return_statement.rb @@ -0,0 +1,9 @@ +module Phisol + Compiler.class_eval do + +# return attr_reader :statement + def on_return statement + return process(statement.to_a.first ) + end + end +end diff --git a/lib/phisol/compiler/statement_list.rb b/lib/phisol/compiler/statement_list.rb new file mode 100644 index 00000000..38b84384 --- /dev/null +++ b/lib/phisol/compiler/statement_list.rb @@ -0,0 +1,8 @@ +module Phisol + Compiler.class_eval do + + def on_statements statement + process_all( statement.children ) + end + end +end diff --git a/lib/phisol/compiler/while_expression.rb b/lib/phisol/compiler/while_statement.rb similarity index 73% rename from lib/phisol/compiler/while_expression.rb rename to lib/phisol/compiler/while_statement.rb index 1eb28cc1..c1e1334c 100644 --- a/lib/phisol/compiler/while_expression.rb +++ b/lib/phisol/compiler/while_statement.rb @@ -1,9 +1,9 @@ module Phisol Compiler.class_eval do - def on_while expression - #puts expression.inspect - condition , expressions = *expression + def on_while statement + #puts statement.inspect + condition , statements = *statement condition = condition.first # this is where the while ends and both branches meet @@ -16,10 +16,10 @@ module Phisol @method.source.add_code Register::IsZeroBranch.new(condition,merge) - last = process_all(expressions).last + last = process_all(statements).last # unconditionally branch to the start - @method.source.add_code Register::AlwaysBranch.new(expression,start) + @method.source.add_code Register::AlwaysBranch.new(statement,start) # continue execution / compiling at the merge block @method.source.current merge diff --git a/lib/virtual/method_source.rb b/lib/virtual/method_source.rb index a7d03a25..89dac00a 100644 --- a/lib/virtual/method_source.rb +++ b/lib/virtual/method_source.rb @@ -108,7 +108,7 @@ module Virtual # happened # But subsequent statements are still using the original block (self) to add code to - # So the while expression creates the extra blocks, adds them and the code and then "moves" + # So the while statement creates the extra blocks, adds them and the code and then "moves" # the insertion point along def current block @current = block diff --git a/test/compiler/test_basic.rb b/test/compiler/test_basic.rb index e4d8d368..c5a2da27 100644 --- a/test/compiler/test_basic.rb +++ b/test/compiler/test_basic.rb @@ -11,11 +11,11 @@ class Object end HERE - expressions = Virtual.machine.boot.parse_and_compile input - if( expressions.first.is_a? Virtual::Self ) - expressions.first.type.instance_variable_set :@of_class , nil + statements = Virtual.machine.boot.parse_and_compile input + if( statements.first.is_a? Virtual::Self ) + statements.first.type.instance_variable_set :@of_class , nil end - is = Sof.write(expressions) + is = Sof.write(statements) #puts is assert_equal @output , is end diff --git a/test/compiler/test_compiler.rb b/test/compiler/test_compiler.rb index 98d2c3a3..4566d3e9 100644 --- a/test/compiler/test_compiler.rb +++ b/test/compiler/test_compiler.rb @@ -7,16 +7,16 @@ class CompilerTest < MiniTest::Test Virtual.machine.boot end def check - res = Phisol::Compiler.compile( @expression ) + res = Phisol::Compiler.compile( @statement ) assert res.is_a?(Virtual::Slot) , "compiler must compile to slot, not #{res.inspect}" end - def test_function_expression - @expression = s(:class, :Foo, + def test_function_statement + @statement = s(:class, :Foo, s(:derives, :Object), - s(:expressions, + s(:statements, s(:function, :int, s(:name, :foo), s(:parameters, s(:parameter, :ref, :x)), - s(:expressions, s(:int, 5))))) + s(:statements, s(:int, 5))))) check end end diff --git a/test/compiler/test_hello.rb b/test/compiler/test_hello.rb index c149665f..109517e0 100644 --- a/test/compiler/test_hello.rb +++ b/test/compiler/test_hello.rb @@ -6,7 +6,7 @@ class HelloTest < MiniTest::Test machine = Virtual.machine.boot Parfait::Space.object_space.get_class_by_name(:Integer).remove_instance_method :plus #TODO remove this hack: write proper aliases - expressions = machine.parse_and_compile @string_input + statements = machine.parse_and_compile @string_input output_at = "Register::CallImplementation" #{}"Register::CallImplementation" machine.run_before output_at diff --git a/test/fragments/helper.rb b/test/fragments/helper.rb index 4f7d1334..07b92e76 100644 --- a/test/fragments/helper.rb +++ b/test/fragments/helper.rb @@ -2,14 +2,14 @@ require_relative '../helper' # simple tests to check parsing pworks and the first classes come out right. # -# build up from small to check larger expressions are correct +# build up from small to check larger statements are correct module Fragments def check - expressions = Virtual.machine.boot.parse_and_compile @string_input + statements = Virtual.machine.boot.parse_and_compile @string_input @expect.each_with_index do | should , i | - exp_i = expressions[i] + exp_i = statements[i] assert exp_i.is_a?(Virtual::Slot) , "compiles should return #{should}, not #{exp_i}" assert_equal should , exp_i.class end diff --git a/test/interpreter/test_add.rb b/test/interpreter/test_add.rb index d26bcc81..5e04aa6f 100644 --- a/test/interpreter/test_add.rb +++ b/test/interpreter/test_add.rb @@ -8,11 +8,11 @@ class AddTest < MiniTest::Test Virtual.machine.boot code = s(:class, :Object, s(:derives, nil), - s(:expressions, + s(:statements, s(:function, :int, s(:name, :main), s(:parameters), - s(:expressions, + s(:statements, s(:call, s(:name, :plus), s(:arguments , s(:int , 5)), diff --git a/test/interpreter/test_puti.rb b/test/interpreter/test_puti.rb index 37a663b8..523f295d 100644 --- a/test/interpreter/test_puti.rb +++ b/test/interpreter/test_puti.rb @@ -53,8 +53,8 @@ HERE puts parts.inspect Phisol::Compiler.compile( parts ) -# expressions = Virtual.machine.boot.parse_and_compile @string_input -# Phisol::Compiler.compile( expressions , Virtual.machine.space.get_main ) +# statements = Virtual.machine.boot.parse_and_compile @string_input +# Phisol::Compiler.compile( statements , Virtual.machine.space.get_main ) Virtual.machine.run_before "Register::CallImplementation" @interpreter = Interpreter::Interpreter.new @interpreter.start Virtual.machine.init diff --git a/test/interpreter/test_puts.rb b/test/interpreter/test_puts.rb index ccdaa5cf..c3c1fd7e 100644 --- a/test/interpreter/test_puts.rb +++ b/test/interpreter/test_puts.rb @@ -7,11 +7,11 @@ class TestPuts < MiniTest::Test Virtual.machine.boot code = s(:class, :Object, s(:derives, nil), - s(:expressions, + s(:statements, s(:function, :int, s(:name, :main), s(:parameters), - s(:expressions, + s(:statements, s(:call, s(:name, :putstring), s(:arguments), diff --git a/test/test_runner.rb b/test/test_runner.rb index 71531dbb..40ae9770 100644 --- a/test/test_runner.rb +++ b/test/test_runner.rb @@ -24,7 +24,7 @@ class TestRunner < MiniTest::Test syntax = parser.parse_with_debug(string) assert syntax parts = Parser::Transform.new.apply(syntax) - # file is a list of expressions, all but the last must be a function + # file is a list of statements, all but the last must be a function # and the last is wrapped as a main parts.each_with_index do |part,index| if index == (parts.length - 1)