add free variable name lookup. Now that we have lexical scope, array comprehensions are greatly improved

This commit is contained in:
Jeremy Ashkenas
2009-12-15 10:28:54 -05:00
parent c7691ecc89
commit aebcc50b05
2 changed files with 28 additions and 16 deletions

View File

@@ -1,6 +1,4 @@
# TODO: switch/case statements
# Flow: For loops, etc.
# Fix array comprehensions -- they're mad busted.
# Think of a name for this crazy thing.
# Functions:
@@ -96,8 +94,8 @@ change_a_and_set_b: =>
b: 15.
b: 20
# For loops.
# foods: ['toast', 'wine', 'cheese']
# print(item.capitalize()) for item in foods.
#
# drink(item) for item in foods if item is 'wine'.
# Array comprehensions.
print(food.capitalize()) for food in ['toast', 'wine', 'cheese'].
cooler: ['soda', 'wine', 'lemonade']
drink(bottle) for bottle in cooler if bottle is 'lemonade'.

View File

@@ -1,21 +1,34 @@
class Scope
attr_reader :parent
attr_reader :parent, :temp_variable
def initialize(parent=nil)
@parent = parent
@variables = {}
@temp_variable = @parent ? @parent.temp_variable : 'a'
end
# Look up a variable in lexical scope, or declare it if not found.
def find(name, remote=false)
return name if @variables[name]
found = @parent && @parent.find(name, true)
found = check(name, remote)
return found if found || remote
@variables[name] = true
found
end
# Just check for the pre-definition of a variable.
def check(name, remote=false)
return true if @variables[name]
@parent && @parent.find(name, true)
end
# Find an available, short variable name.
def free_variable
@temp_variable.succ! while check(@temp_variable)
@variables[@temp_variable] = true
@temp_variable.dup
end
end
class Node
@@ -318,9 +331,6 @@ class WhileNode < Node
end
class ForNode < Node
I = "__i__"
L = "__l__"
S = "__s__"
def initialize(body, name, source, condition=nil)
@body, @name, @source, @condition = body, name, source, condition
@@ -335,9 +345,13 @@ class ForNode < Node
end
def compile(indent, scope, opts={})
source_part = "var #{S} = #{@source.compile(indent, scope)};"
for_part = "var #{I}=0, #{L}=#{S}.length; #{I}<#{L}; #{I}++"
var_part = "\n#{indent + TAB}var #{@name} = #{S}[#{I}];"
svar = scope.free_variable
ivar = scope.free_variable
lvar = scope.free_variable
name_part = scope.find(@name) ? @name : "var #{@name}"
source_part = "var #{svar} = #{@source.compile(indent, scope)};"
for_part = "var #{ivar}=0, #{lvar}=#{svar}.length; #{ivar}<#{lvar}; #{ivar}++"
var_part = "\n#{indent + TAB}#{name_part} = #{svar}[#{ivar}];"
"#{source_part}\n#{indent}for (#{for_part}) {#{var_part}\n#{indent + TAB}#{@body.compile(indent + TAB, scope)};\n#{indent}}"
end
end