Skip to content

Commit

Permalink
Any function supports dereferencing now. Also traits
Browse files Browse the repository at this point in the history
  • Loading branch information
Josep M. Bach committed Sep 18, 2011
1 parent 8f387b8 commit 01cd5eb
Show file tree
Hide file tree
Showing 12 changed files with 395 additions and 327 deletions.
4 changes: 3 additions & 1 deletion examples/traits.ns
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
Runnable = trait({
run: -> speed
print('running with traits at speed:', speed)
print(@name, 'is running with traits at speed:', speed)
end
})

person = Object.clone()
person.uses(Runnable)

person.name = 'John'

person.run(10)
17 changes: 14 additions & 3 deletions lib/noscript/ast.rb
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,13 @@ def compile(context)
end
end

class Identifier < Struct.new(:name)
class Identifier < Struct.new(:name, :deref)
def compile(context)
context.lookup_var(name)
if deref
context.current_receiver.slots[name]
else
context.lookup_var(name)
end
end
def to_s
name
Expand Down Expand Up @@ -76,17 +80,24 @@ def compile(context)

class Message < Struct.new(:receiver, :slot)
def compile(context)
ctx = Context.new(context)
ctx.current_receiver = context.current_receiver

if receiver
# rcv.foo() looks up the message in the receiver slots
rcv = receiver.compile(context)

# Save a reference to the current receiver
ctx.current_receiver = rcv

retval = rcv.send(name)
else
# foo() looks up a function in the global context
retval = context.lookup_var(name)
end

if call?
retval.call(context, *arguments)
retval.call(ctx, *arguments)
else
retval
end
Expand Down
3 changes: 1 addition & 2 deletions lib/noscript/context.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,11 @@ def self.generate
ctx
end

attr_accessor :lvars, :methods
attr_accessor :lvars, :current_receiver

def initialize(parent_context = nil)
@parent = parent_context
@lvars = {}
@methods = {}
end

def lookup_var(symbol)
Expand Down
2 changes: 2 additions & 0 deletions lib/noscript/method.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ def call(context, *args)
raise_argument_error(args) if args.size > params.size

ctx = Context.new(context)
ctx.current_receiver = context.current_receiver

params.each_with_index do |param, idx|
if passed_value = args[idx]
ctx.store_var(param.name, passed_value.compile(ctx))
Expand Down
1 change: 1 addition & 0 deletions lib/noscript/parser/noscript.racc
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ rule
while : WHILE expression end_of_statement statements END { result = AST::WhileNode.new(val[1], val[3]) }

identifier : IDENTIFIER { result = AST::Identifier.new(val[0]) }
| DEREF { result = AST::Identifier.new(val[0], true)}

digit : DIGIT { result = AST::Digit.new(val[0]) }
string : STRING { result = AST::String.new(val[0]) }
Expand Down
1 change: 1 addition & 0 deletions lib/noscript/parser/noscript.rex
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ rule
else { [:ELSE, text] }
while { [:WHILE, text] }
@\w[{BLANK}\w]* { [:DEREF, text.strip[1..-1]] }
\w[{BLANK}\w]* { [:IDENTIFIER, text.strip] }
\s
Expand Down
3 changes: 3 additions & 0 deletions lib/noscript/parser/noscript.rex.rb
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,9 @@ def _next_token
when (text = @ss.scan(/while/))
action { [:WHILE, text] }

when (text = @ss.scan(/@\w[[ ]\w]*/))
action { [:DEREF, text.strip[1..-1]] }

when (text = @ss.scan(/\w[[ ]\w]*/))
action { [:IDENTIFIER, text.strip] }

Expand Down
666 changes: 347 additions & 319 deletions lib/noscript/parser/noscript.tab.rb

Large diffs are not rendered by default.

1 change: 0 additions & 1 deletion test/context_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ class ContextTest < MiniTest::Unit::TestCase
def setup
@context = Noscript::Context.new
@context.lvars = { 'foo' => 3 }
@context.methods = { 'lorem' => proc { 'ipsum' } }
end

# Local variable lookup and storage
Expand Down
3 changes: 2 additions & 1 deletion test/integration_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@ def test_traits
output = `./bin/noscript examples/traits.ns`.split("\n")

assert_equal [
"running with traits at speed:",
"John",
"is running with traits at speed:",
"10"
], output
end
Expand Down
4 changes: 4 additions & 0 deletions test/lexer/lexer_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -95,4 +95,8 @@ def test_fun
tokenizes "->", [[:FUN, '->']]
end

def test_deref
tokenizes "@name", [[:DEREF, 'name']]
end

end
17 changes: 17 additions & 0 deletions test/method_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -104,4 +104,21 @@ def test_method_with_too_many_arguments
end
end

def test_method_with_dereferencing
# -> bar=23
# a = 3
# 74
# @foo
# end
@method.body.nodes.push(
Noscript::AST::Identifier.new('foo', true)
)
object = Noscript::Object.new
object.add_slot('foo', Noscript::AST::Digit.new(123))

@context.current_receiver = object

assert_equal Noscript::AST::Digit.new(123), @method.call(@context)
end

end

0 comments on commit 01cd5eb

Please sign in to comment.