package org.yinwang.yin;


import org.yinwang.yin.value.BoolType;
import org.yinwang.yin.value.BoolValue;
import org.yinwang.yin.value.IntType;
import org.yinwang.yin.value.Value;
import org.yinwang.yin.value.primitives.*;

import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;

public class Scope {

    public Map<String, Map<String, Object>> table = new HashMap<>();
    public Scope parent;


    public Scope() {
        this.parent = null;
    }


    public Scope(Scope parent) {
        this.parent = parent;
    }


    public Value lookupLocal(String name) {
        Object v = lookupLocalItem(name, "value");
        if (v == null) {
            return null;
        } else if (v instanceof Value) {
            return (Value) v;
        } else {
            _.abort("value is not a Value, shouldn't happen: " + v);
            return null;
        }
    }


    public Value lookup(String name) {
        Object v = lookupLocalItem(name, "value");
        if (v == null) {
            if (parent != null) {
                return parent.lookup(name);
            } else {
                return null;
            }
        } else if (v instanceof Value) {
            return (Value) v;
        } else {
            _.abort("value is not a Value, shouldn't happen: " + v);
            return null;
        }
    }


    public Object lookupLocalItem(String name, String key) {
        Map<String, Object> item = table.get(name);
        if (item != null) {
            return item.get(key);
        } else {
            return null;
        }
    }


    public Object lookupItem(String name, String key) {
        Object v = lookupLocalItem(name, key);
        if (v != null) {
            return v;
        } else if (parent != null) {
            return parent.lookupItem(name, key);
        } else {
            return null;
        }
    }


    public Scope findDefiningScope(String name) {
        Object v = table.get(name);
        if (v != null) {
            return this;
        } else if (parent != null) {
            return parent.findDefiningScope(name);
        } else {
            return null;
        }
    }


    public static Scope buildInitScope() {
        Scope init = new Scope();

        init.putValue("+", new Add());
        init.putValue("-", new Sub());
        init.putValue("*", new Mult());
        init.putValue("/", new Div());

        init.putValue("<", new Lt());
        init.putValue("<=", new LtE());
        init.putValue(">", new Gt());
        init.putValue(">=", new GtE());
        init.putValue("=", new Eq());
        init.putValue("and", new And());
        init.putValue("or", new Or());
        init.putValue("not", new Not());

        init.putValue("true", new BoolValue(true));
        init.putValue("false", new BoolValue(false));

        init.putValue("Int", new IntType());
        init.putValue("Bool", new BoolType());

        return init;
    }


    public void put(String name, String key, Object value) {
        Map<String, Object> item = table.get(name);
        if (item == null) {
            item = new LinkedHashMap<>();
        }
        item.put(key, value);
        table.put(name, item);
    }


    public void putValue(String name, Object value) {
        put(name, "value", value);
    }

}

@@ -567,21 +567,16 @@
 e lookup
-Local
 (String 
@@ -604,33 +604,32 @@
 t v = lookup
-LocalItem
+Property
 (name, %22valu
@@ -898,32 +898,37 @@
 lic Value lookup
+Local
 (String name) %7B%0A
@@ -948,33 +948,37 @@
 t v = lookup
+Property
 Local
-Item
 (name, %22valu
@@ -1023,137 +1023,20 @@
     
-if (parent != null) %7B%0A                return parent.lookup(name);%0A            %7D else %7B%0A                return null;%0A            %7D
+return null;
 %0A   
@@ -1256,25 +1256,29 @@
 t lookup
+Property
 Local
-Item
 (String 
@@ -1495,20 +1495,24 @@
 t lookup
-Item
+Property
 (String 
@@ -1560,17 +1560,21 @@
 okup
+Property
 Local
-Item
 (nam
@@ -1702,12 +1702,16 @@
 okup
-Item
+Property
 (nam

simplify and renaming