Skip to content
Browse files

Added code to capture a function's actual source string from the pars…

…er and

attach it to the function object.  This needs to be expanded / refactored, but
I'm leaving it as an example to follow later.
  • Loading branch information...
1 parent 95b0d32 commit 7c68f51a0561f121f9e08b2d4f74c4c0cd248fcd @eki committed Nov 6, 2011
Showing with 35 additions and 17 deletions.
  1. +9 −3 lib/p/core/function.rb
  2. +1 −0 lib/p/expr.rb
  3. +3 −1 lib/p/exprs/fn.rb
  4. +0 −2 lib/p/exprs/number.rb
  5. +14 −5 lib/p/parser.rb
  6. +4 −3 lib/p/scanner.rb
  7. +4 −3 lib/p/token.rb
View
12 lib/p/core/function.rb
@@ -126,11 +126,12 @@ def bind_by_name( parameters, environment, to_env )
end
end
- class Function
- attr_reader :parameters, :code
+ class Function < Object
+ attr_reader :parameters, :code, :source, :parameters_source
- def initialize( parameters=[], code=nil )
+ def initialize( parameters=[], code=nil, source=nil, parameters_source=nil )
@parameters, @code = parameters, code
+ @source, @parameters_source = source, parameters_source
end
def eval( args, args_env, exec_env )
@@ -145,6 +146,10 @@ def inspect
def to_s
inspect
end
+
+ receive( :code ) { |env| code.to_s }
+ receive( :source ) { |env| source }
+ receive( :parameters_source ) { |env| parameters_source }
end
class Closure < Object
@@ -184,6 +189,7 @@ def to_s
end
receive( :environment ) { |env| environment }
+ receive( :function ) { |env| function }
receive( :to_string ) { |env| to_s }
receive( :call, 'args: *' ) do |env|
View
1 lib/p/expr.rb
@@ -2,6 +2,7 @@
module P
class Expr
+ attr_accessor :position
attr_reader :name, :list
def initialize( *list )
View
4 lib/p/exprs/fn.rb
@@ -2,9 +2,11 @@
module P
class FnExpr < Expr
+ attr_accessor :source, :parameters_source
def evaluate( environment )
- Closure.new( Function.new( left.evaluate, right ), environment )
+ fn = Function.new( left.evaluate, right, source, parameters_source )
+ Closure.new( fn, environment )
end
end
View
2 lib/p/exprs/number.rb
@@ -11,8 +11,6 @@ def to_s
value.value
end
- ZERO = NumberExpr.new( Token.new( :number, 0, 0, 0 ) )
-
end
end
View
19 lib/p/parser.rb
@@ -580,7 +580,12 @@ def params_to_args( params )
infix( :fn, '*', :right, block: true ) do |t,left,right|
right = Expr.block( right ) unless right.block?
- Expr.fn( left.to_params, right )
+ e = Expr.fn( left.to_params, right )
+ if left.position
+ e.source = source[(left.position+1)..(top.position)]
+ e.parameters_source = source[(left.position+1)..(t.position)]
+ end
+ e
end
infix( :comma, 5 ) { |t,left,right| Expr.seq( left, right ) }
@@ -655,7 +660,9 @@ def params_to_args( params )
raise "Expected ) got #{t}" unless consume( :close_paren )
end
- expr || Expr.seq
+ e = expr || Expr.seq
+ e.position = t.position
+ e
end
prefix( :open_curly ) do |t|
@@ -688,12 +695,14 @@ def params_to_args( params )
prefix( :fn ) do |t|
if top === :newline && parse_line_separator
- Expr.fn( Expr.params, parse_block( t.indent ) )
+ e = Expr.fn( Expr.params, parse_block( t.indent ) )
elsif expr = parse_expression
- Expr.fn( Expr.params, Expr.block( expr ) )
+ e = Expr.fn( Expr.params, Expr.block( expr ) )
else
- Expr.fn( Expr.params, Expr.block )
+ e = Expr.fn( Expr.params, Expr.block )
end
+ e.source = source[(t.position+1)..(top.position)]
+ e
end
prefix( :not, 18 )
View
7 lib/p/scanner.rb
@@ -59,7 +59,8 @@ def next_token( context )
end
unless r[:nop]
- token = Token.new( r[:name], m, line, character, indent )
+ token = Token.new( r[:name], m, position, line, character,
+ indent )
end
if r[:indent]
@@ -78,9 +79,9 @@ def next_token( context )
@last_token = token
else
if last_token.nil?
- @last_token = Token.new( :start, '', line, character, 0 )
+ @last_token = Token.new( :start, '', position, line, character, 0 )
else
- @last_token = Token.new( :end, '', line, character, -1 )
+ @last_token = Token.new( :end, '', position, line, character, -1 )
end
end
end
View
7 lib/p/token.rb
@@ -2,10 +2,11 @@
module P
class Token
- attr_reader :name, :value, :line, :character, :indent
+ attr_reader :name, :value, :position, :line, :character, :indent
- def initialize( name, value, line, character, indent=nil )
- @name, @value, @line, @character = name.to_sym, value, line, character
+ def initialize( name, value, position, line, character, indent=nil )
+ @name, @value = name.to_sym, value
+ @position, @line, @character = position, line, character
@indent = indent
end

0 comments on commit 7c68f51

Please sign in to comment.
Something went wrong with that request. Please try again.