Permalink
Browse files

calling forms

  • Loading branch information...
Josep M. Bach
Josep M. Bach committed May 12, 2012
1 parent d081769 commit 59474df70ba3d2cb601fe1992096351032fe914a
View
@@ -0,0 +1,30 @@
+require 'set'
+
+class Function
+ def initialize(&block)
+ @block = block
+ end
+ def call(*args)
+ @block.call(*args)
+ end
+end
+
+class GlobalScope < Hash
+ def self.bootstrap
+ scope = new
+ scope[:println] = Function.new { |*args| puts *args }
+ scope[:+] = Function.new { |*args| args.inject(:+) }
+ scope[:-] = Function.new { |*args| args.inject(:-) }
+ scope[:/] = Function.new { |a, b| a / b }
+ scope[:*] = Function.new { |a, b| a * b }
+ scope
+ end
+end
+
+Scope = GlobalScope.bootstrap
+
+class Keyword
+ def initialize(name)
+ @name = name
+ end
+end
@@ -32,6 +32,26 @@ def compile(ast, debugging=false)
def visit_List(o)
set_line(o)
return g.push_nil if o.elements.count.zero?
+ car = o.elements[0]
+ cdr = o.elements[1..-1]
+ args = cdr.count
+
+ visit_Symbol(car)
+
+ # TODO: lazy evaluation
+ cdr.each do |arg|
+ arg.accept(self)
+ end
+
+ g.send :call, args
+ end
+
+ def visit_Symbol(o)
+ set_line(o)
+ g.push_cpath_top
+ g.find_const :Scope
+ g.push_literal o.name
+ g.send :fetch, 1
end
def visit_Number(o)
@@ -1,16 +1,47 @@
module Lambra
class CodeLoader
def self.evaluate(string)
- ast = Lambra::Parser.parse string
+ ast = Lambra::Parser.parse string
+ execute(ast)
+ end
+
+ def self.execute(ast)
visitor = BytecodeCompiler.new
- cm = visitor.compile(ast)
+ gen = visitor.compile(ast)
+ gen.encode
+ cm = gen.package Rubinius::CompiledMethod
+
+ require_relative '../bootstrap'
+
+ env = Scope
+
+ file = if ast.respond_to?(:filename) && ast.filename
+ ast.filename
+ else
+ '(eval)'
+ end
+
+ line, binding, instance = ast.line, env.send(:binding), env
+
+ # cm = Noscript::Compiler.compile_eval(code, binding.variables, file, line)
+ cm.scope = Rubinius::StaticScope.new(GlobalScope)
+ cm.name = :__lambra__
+ script = Rubinius::CompiledMethod::Script.new(cm, file, true)
+ be = Rubinius::BlockEnvironment.new
+
+ script.eval_binding = binding
+ # script.eval_source = string
+ cm.scope.script = script
+
+ be.under_context(binding.variables, cm)
+ be.from_eval!
+ be.call_on_instance(instance)
end
def self.execute_file(name)
ast = Lambra::Parser.parse IO.read(name)
def ast.filename; name; end
- visitor = BytecodeCompiler.new
- cm = visitor.compile(ast)
+ execute(ast)
end
end
end
@@ -39,7 +39,7 @@ true = "true" ~true_value(current_line, current_column)
false = "false" ~false_value(current_line, current_column)
nil = "nil" ~nil_value(current_line, current_column)
-word = < /[a-zA-Z_\*][a-zA-Z0-9_\-\*]*/ > { text }
+word = < /[a-zA-Z0-9_\-\*\+\-\/]+/ > { text }
symbol = word:w ~symbol(current_line, current_column, w.to_sym)
keyword = ":" word:w ~keyword(current_line, current_column, w.to_sym)
@@ -856,13 +856,13 @@ def _nil
return _tmp
end
- # word = < /[a-zA-Z_\*][a-zA-Z0-9_\-\*]*/ > { text }
+ # word = < /[a-zA-Z0-9_\-\*\+\-\/]+/ > { text }
def _word
_save = self.pos
while true # sequence
_text_start = self.pos
- _tmp = scan(/\A(?-mix:[a-zA-Z_\*][a-zA-Z0-9_\-\*]*)/)
+ _tmp = scan(/\A(?-mix:[a-zA-Z0-9_\-\*\+\-\/]+)/)
if _tmp
text = get_text(_text_start)
end
@@ -1641,7 +1641,7 @@ def _root
Rules[:_true] = rule_info("true", "\"true\" {true_value(current_line, current_column)}")
Rules[:_false] = rule_info("false", "\"false\" {false_value(current_line, current_column)}")
Rules[:_nil] = rule_info("nil", "\"nil\" {nil_value(current_line, current_column)}")
- Rules[:_word] = rule_info("word", "< /[a-zA-Z_\\*][a-zA-Z0-9_\\-\\*]*/ > { text }")
+ Rules[:_word] = rule_info("word", "< /[a-zA-Z0-9_\\-\\*\\+\\-\\/]+/ > { text }")
Rules[:_symbol] = rule_info("symbol", "word:w {symbol(current_line, current_column, w.to_sym)}")
Rules[:_keyword] = rule_info("keyword", "\":\" word:w {keyword(current_line, current_column, w.to_sym)}")
Rules[:_string] = rule_info("string", "\"\\\"\" < /[^\\\\\"]*/ > \"\\\"\" {string_value(current_line, current_column, text)}")
View
@@ -0,0 +1,7 @@
+require 'spec_helper'
+
+describe "Environment bootstrap" do
+ describe 'println' do
+ Lambra::CodeLoader.evaluate '(println "hello")'
+ end
+end

0 comments on commit 59474df

Please sign in to comment.