define modules and tests, no compiling
This commit is contained in:
parent
d59370bdc7
commit
c69a44f316
@ -9,7 +9,7 @@
|
|||||||
|
|
||||||
module Ast
|
module Ast
|
||||||
class Expression
|
class Expression
|
||||||
def eval
|
def compile context , into
|
||||||
raise "abstract #{self}"
|
raise "abstract #{self}"
|
||||||
end
|
end
|
||||||
def compile context , into
|
def compile context , into
|
||||||
@ -33,10 +33,11 @@ module Ast
|
|||||||
end
|
end
|
||||||
|
|
||||||
require_relative "basic_expressions"
|
require_relative "basic_expressions"
|
||||||
|
require_relative "call_site_expression"
|
||||||
require_relative "compound_expressions"
|
require_relative "compound_expressions"
|
||||||
require_relative "if_expression"
|
require_relative "if_expression"
|
||||||
require_relative "while_expression"
|
|
||||||
require_relative "return_expression"
|
|
||||||
require_relative "function_expression"
|
require_relative "function_expression"
|
||||||
|
require_relative "module_expression"
|
||||||
require_relative "operator_expressions"
|
require_relative "operator_expressions"
|
||||||
require_relative "call_site_expression"
|
require_relative "return_expression"
|
||||||
|
require_relative "while_expression"
|
||||||
|
34
lib/ast/module_expression.rb
Normal file
34
lib/ast/module_expression.rb
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
module Ast
|
||||||
|
class ModuleExpression < Expression
|
||||||
|
attr_reader :name ,:expressions
|
||||||
|
def initialize name , expressions
|
||||||
|
@name = name.to_sym
|
||||||
|
@expressions = expressions
|
||||||
|
end
|
||||||
|
def inspect
|
||||||
|
self.class.name + ".new(" + @name.inspect + " ," + @expressions.inspect + " )"
|
||||||
|
end
|
||||||
|
def to_s
|
||||||
|
"module #{name}\n #{expressions}\nend\n"
|
||||||
|
end
|
||||||
|
def attributes
|
||||||
|
[:name , :expressions]
|
||||||
|
end
|
||||||
|
def compile context , into
|
||||||
|
expression_value = expression.compile(context , into)
|
||||||
|
puts "compiled return expression #{expression_value.inspect}, now return in 7"
|
||||||
|
# copied from function expression: TODO make function
|
||||||
|
|
||||||
|
return_reg = Vm::Integer.new(7)
|
||||||
|
if expression_value.is_a?(Vm::IntegerConstant) or expression_value.is_a?(Vm::StringConstant)
|
||||||
|
return_reg.load into , expression_value if expression_value.register != return_reg.register
|
||||||
|
else
|
||||||
|
return_reg.move( into, expression_value ) if expression_value.register != return_reg.register
|
||||||
|
end
|
||||||
|
#function.set_return return_reg
|
||||||
|
return return_reg
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
end
|
@ -6,6 +6,7 @@ require_relative "control"
|
|||||||
require_relative "expression"
|
require_relative "expression"
|
||||||
require_relative "call_site"
|
require_relative "call_site"
|
||||||
require_relative "function_definition"
|
require_relative "function_definition"
|
||||||
|
require_relative "module_def"
|
||||||
require_relative "operators"
|
require_relative "operators"
|
||||||
|
|
||||||
module Parser
|
module Parser
|
||||||
@ -28,7 +29,8 @@ module Parser
|
|||||||
include CallSite
|
include CallSite
|
||||||
include FunctionDefinition
|
include FunctionDefinition
|
||||||
include Operators
|
include Operators
|
||||||
|
include ModuleDef
|
||||||
|
|
||||||
rule(:root){ (function_definition | expression | call_site | space).repeat }
|
rule(:root){ (function_definition | expression | call_site ).repeat }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -3,6 +3,7 @@ module Parser
|
|||||||
include Parslet
|
include Parslet
|
||||||
|
|
||||||
rule(:keyword_begin) { str('begin').as(:begin) >> space?}
|
rule(:keyword_begin) { str('begin').as(:begin) >> space?}
|
||||||
|
rule(:keyword_class) { str('class') >> space? }
|
||||||
rule(:keyword_def) { str('def') >> space? }
|
rule(:keyword_def) { str('def') >> space? }
|
||||||
rule(:keyword_do) { str('do').as(:do) >> space?}
|
rule(:keyword_do) { str('do').as(:do) >> space?}
|
||||||
rule(:keyword_else) { str('else').as(:else) >> space? }
|
rule(:keyword_else) { str('else').as(:else) >> space? }
|
||||||
@ -12,6 +13,7 @@ module Parser
|
|||||||
rule(:keyword_rescue) { str('rescue').as(:rescue) >> space?}
|
rule(:keyword_rescue) { str('rescue').as(:rescue) >> space?}
|
||||||
rule(:keyword_return) { str('return').as(:return) >> space?}
|
rule(:keyword_return) { str('return').as(:return) >> space?}
|
||||||
rule(:keyword_true) { str('true').as(:true) >> space?}
|
rule(:keyword_true) { str('true').as(:true) >> space?}
|
||||||
|
rule(:keyword_module) { str('module') >> space? }
|
||||||
rule(:keyword_nil) { str('nil').as(:nil) >> space?}
|
rule(:keyword_nil) { str('nil').as(:nil) >> space?}
|
||||||
rule(:keyword_unless) { str('unless').as(:unless) >> space?}
|
rule(:keyword_unless) { str('unless').as(:unless) >> space?}
|
||||||
rule(:keyword_until) { str('until').as(:until) >> space?}
|
rule(:keyword_until) { str('until').as(:until) >> space?}
|
||||||
|
9
lib/parser/module_def.rb
Normal file
9
lib/parser/module_def.rb
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
module Parser
|
||||||
|
module ModuleDef
|
||||||
|
include Parslet
|
||||||
|
rule(:module_def) do
|
||||||
|
keyword_module >> name >> eol >>
|
||||||
|
( (keyword_end.absent? >> root).repeat(1)).as(:module_expressions) >> keyword_end >> newline
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
@ -53,6 +53,10 @@ module Parser
|
|||||||
Ast::OperatorExpression.new( o.to_s.strip , l ,r)
|
Ast::OperatorExpression.new( o.to_s.strip , l ,r)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
rule( :name => simple(:name) , :module_expressions => sequence(:module_expressions) , :end=>"end") do
|
||||||
|
Ast::ModuleExpression.new(name , module_expressions)
|
||||||
|
end
|
||||||
|
|
||||||
#shortcut to get the ast tree for a given string
|
#shortcut to get the ast tree for a given string
|
||||||
# optional second arguement specifies a rule that will be parsed (mainly for testing)
|
# optional second arguement specifies a rule that will be parsed (mainly for testing)
|
||||||
def self.ast string , rule = :root
|
def self.ast string , rule = :root
|
||||||
|
@ -37,9 +37,9 @@ module ParserHelper
|
|||||||
# check that @string_input parses and transforms to @transform_output
|
# check that @string_input parses and transforms to @transform_output
|
||||||
def check_ast
|
def check_ast
|
||||||
syntax = @parser.parse(@string_input)
|
syntax = @parser.parse(@string_input)
|
||||||
tree = @transform.apply(syntax)
|
is = @transform.apply(syntax)
|
||||||
# puts tree.inspect
|
#puts is.inspect
|
||||||
assert_equal @transform_output , tree
|
assert_equal @transform_output , is
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
|
|
||||||
require_relative "test_basic"
|
|
||||||
require_relative "test_compound"
|
|
||||||
require_relative "test_arguments"
|
require_relative "test_arguments"
|
||||||
require_relative "test_expressions"
|
require_relative "test_basic"
|
||||||
require_relative "test_call_site"
|
require_relative "test_call_site"
|
||||||
|
require_relative "test_compound"
|
||||||
require_relative "test_conditional"
|
require_relative "test_conditional"
|
||||||
require_relative "test_while"
|
require_relative "test_expressions"
|
||||||
require_relative "test_return"
|
|
||||||
require_relative "test_operators"
|
|
||||||
require_relative "test_function_definition"
|
require_relative "test_function_definition"
|
||||||
|
require_relative "test_module"
|
||||||
|
require_relative "test_operators"
|
||||||
|
require_relative "test_return"
|
||||||
require_relative "test_root"
|
require_relative "test_root"
|
||||||
|
require_relative "test_while"
|
||||||
|
62
test/parser/test_module.rb
Normal file
62
test/parser/test_module.rb
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
require_relative "helper"
|
||||||
|
|
||||||
|
class TestModuleDef < MiniTest::Test
|
||||||
|
# include the magic (setup and parse -> test method translation), see there
|
||||||
|
include ParserHelper
|
||||||
|
|
||||||
|
def test_simplest_module
|
||||||
|
@string_input = <<HERE
|
||||||
|
module foo
|
||||||
|
5
|
||||||
|
end
|
||||||
|
HERE
|
||||||
|
@parse_output = {:name=>"foo", :module_expressions=>[{:integer=>"5"}], :end=>"end"}
|
||||||
|
@transform_output = Ast::ModuleExpression.new("foo" ,[Ast::IntegerExpression.new(5)] )
|
||||||
|
@parser = @parser.module_def
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_module_ops
|
||||||
|
@string_input = <<HERE
|
||||||
|
module ops
|
||||||
|
def foo(x)
|
||||||
|
abba = 5
|
||||||
|
2 + 5
|
||||||
|
end
|
||||||
|
end
|
||||||
|
HERE
|
||||||
|
@parse_output = {:name=>"ops", :module_expressions=>[{:function_name=>{:name=>"foo"}, :parmeter_list=>[{:parmeter=>{:name=>"x"}}], :expressions=>[{:l=>{:name=>"abba"}, :o=>"= ", :r=>{:integer=>"5"}}, {:l=>{:integer=>"2"}, :o=>"+ ", :r=>{:integer=>"5"}}], :end=>"end"}], :end=>"end"}
|
||||||
|
@transform_output = Ast::ModuleExpression.new("ops" ,[Ast::FunctionExpression.new(:foo, [Ast::NameExpression.new("x")] , [Ast::OperatorExpression.new("=", Ast::NameExpression.new("abba"),Ast::IntegerExpression.new(5)),Ast::OperatorExpression.new("+", Ast::IntegerExpression.new(2),Ast::IntegerExpression.new(5))] )] )
|
||||||
|
@parser = @parser.module_def
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_module_if
|
||||||
|
@string_input = <<HERE
|
||||||
|
module sif
|
||||||
|
def ofthen(n)
|
||||||
|
if(0)
|
||||||
|
isit = 42
|
||||||
|
else
|
||||||
|
maybenot = 667
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
HERE
|
||||||
|
@parse_output = {:name=>"sif", :module_expressions=>[{:function_name=>{:name=>"ofthen"}, :parmeter_list=>[{:parmeter=>{:name=>"n"}}], :expressions=>[{:if=>"if", :conditional=>{:integer=>"0"}, :if_true=>{:expressions=>[{:l=>{:name=>"isit"}, :o=>"= ", :r=>{:integer=>"42"}}], :else=>"else"}, :if_false=>{:expressions=>[{:l=>{:name=>"maybenot"}, :o=>"= ", :r=>{:integer=>"667"}}], :end=>"end"}}], :end=>"end"}], :end=>"end"}
|
||||||
|
@transform_output = Ast::ModuleExpression.new("sif" ,[Ast::FunctionExpression.new(:ofthen, [Ast::NameExpression.new("n")] , [Ast::IfExpression.new(Ast::IntegerExpression.new(0), [Ast::OperatorExpression.new("=", Ast::NameExpression.new("isit"),Ast::IntegerExpression.new(42))],[Ast::OperatorExpression.new("=", Ast::NameExpression.new("maybenot"),Ast::IntegerExpression.new(667))] )] )] )
|
||||||
|
@parser = @parser.module_def
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_module_function
|
||||||
|
@string_input = <<HERE
|
||||||
|
module sif
|
||||||
|
ofthen(3+4 , var)
|
||||||
|
def ofthen(n,m)
|
||||||
|
44
|
||||||
|
end
|
||||||
|
end
|
||||||
|
HERE
|
||||||
|
@parse_output = {:name=>"sif", :module_expressions=>[{:call_site=>{:name=>"ofthen"}, :argument_list=>[{:argument=>{:l=>{:integer=>"3"}, :o=>"+", :r=>{:integer=>"4"}}}, {:argument=>{:name=>"var"}}]}, {:function_name=>{:name=>"ofthen"}, :parmeter_list=>[{:parmeter=>{:name=>"n"}}, {:parmeter=>{:name=>"m"}}], :expressions=>[{:integer=>"44"}], :end=>"end"}], :end=>"end"}
|
||||||
|
@transform_output = Ast::ModuleExpression.new(:sif ,[Ast::CallSiteExpression.new(:ofthen, [Ast::OperatorExpression.new("+", Ast::IntegerExpression.new(3),Ast::IntegerExpression.new(4)),Ast::NameExpression.new("var")] ), Ast::FunctionExpression.new(:ofthen, [Ast::NameExpression.new("n"),Ast::NameExpression.new("m")] , [Ast::IntegerExpression.new(44)] )] )
|
||||||
|
@parser = @parser.module_def
|
||||||
|
end
|
||||||
|
end
|
Loading…
Reference in New Issue
Block a user