]> git.mdlowis.com Git - proto/sclpl-rb.git/commitdiff
added specs for symtable
authorMichael D. Lowis <mike@mdlowis.com>
Sat, 4 Jul 2020 03:09:33 +0000 (23:09 -0400)
committerMichael D. Lowis <mike@mdlowis.com>
Sat, 4 Jul 2020 03:09:33 +0000 (23:09 -0400)
lib/dyn.rb
spec/symtable_spec.rb

index 356fc6b770c3bbafef78f6d2a995f6f1318e1e4e..70ebc5d1f12e1806f30fbb0a932d907e304598ac 100755 (executable)
@@ -14,6 +14,8 @@ def error(loc, msg)
 end
 
 class SymTable < Hash
+  attr_accessor :is_func
+
   def initialize(parent = nil)
     @parent = (parent || {})
   end
@@ -34,20 +36,30 @@ class SymTable < Hash
     super(key,value)
   end
 
-  def local?(key)
+  def block_local?(key)
     (not method(:[]).super_method.call(key).nil?)
   end
 
   def global?(key)
     if @parent.class == Hash
-      local?(key)
-    elsif local? key
+      block_local?(key)
+    elsif block_local? key
       false
     else
       @parent.global? key
     end
   end
 
+  def local?(key)
+    if @parent.class == Hash
+      false
+    elsif is_func
+      block_local? key
+    else
+      @parent.local? key
+    end
+  end
+
   def merge!(env)
     env.each {|k,v| self[k] = v }
   end
index 45f6c5522cd0ee5eb5cae847dc7d8a5e9df949e7..c4073c004c55d2e5d4dab176788b316714b0f65b 100644 (file)
@@ -1,16 +1,68 @@
 require "dyn"
 
 describe SymTable do
-#  subject {
-#    symtab = SymTable.new
-#    symtab[:a] = {}
-#    symtab
-#  }
-
-#  context ".clone" do
-#    if "keeps a reference to the parent environment when cloned" do
-#      symtab = SymTable.new("foo")
-#      expect(symtab.instance_variable_get(:@parent)).to eq "foo"
-#    end
-#  end
+  subject {
+    symtab1 = SymTable.new
+    symtab1[:a] = {}
+    symtab1[:d] = {}
+    symtab2 = symtab1.clone
+    symtab2.is_func = true
+    symtab2[:b] = {}
+    symtab3 = symtab2.clone
+    symtab3[:c] = {}
+    symtab3[:d] = {}
+    symtab3
+  }
+
+  it "keeps a reference to the parent environment when cloned" do
+    symtab = SymTable.new("foo")
+    expect(symtab.instance_variable_get(:@parent)).to eq "foo"
+  end
+
+  context "lookup/store" do
+    it "will find the symbol in the inner most context" do
+      expect(subject[:c]).to eq({})
+    end
+
+    it "will find the symbol in global context" do
+      expect(subject[:a]).to eq({})
+    end
+
+    it "will find the symbol in the middle context" do
+      expect(subject[:b]).to eq({})
+    end
+
+    it "will return nil if no symbol defined with the given name" do
+      expect(subject[:z]).to eq(nil)
+    end
+  end
+
+  context "global?" do
+    it "returns true if the symbol is defined in global context" do
+      expect(subject.global? :a).to eq true
+    end
+
+    it "returns false if the symbol is defined in non-global context" do
+      expect(subject.global? :b).to eq false
+    end
+  end
+
+  context "local?" do
+    it "returns true if the symbol is defined in local function context" do
+      expect(subject.local? :b).to eq true
+    end
+    it "returns false if the symbol is defined outside of the current function context" do
+      expect(subject.local? :a).to eq false
+    end
+  end
+
+  context "block_local?" do
+    it "returns true if the symbol is defined in context of the inner most block" do
+      expect(subject.block_local? :d).to eq true
+    end
+
+    it "returns false if the symbol is defined outside the context of the inner most block" do
+      expect(subject.block_local? :b).to eq false
+    end
+  end
 end
\ No newline at end of file