見出し画像

FR2と意味解析

どーも、どーも、こんばんわー、ハルキーです。
今日はFR2の話をしていきたいと思います。

意味解析のコード数は3500行くらいで、前回の870行と合わせて、4400行くらいですかね。

二つ目のコードのObjの単位に分けて、これをPlus,Minus,FeelResult,ResultReasonなどの機能をOverrideして、処理が完了するようになってます。
if elseなどは、手前の実行結果を保存しておいて、確認しています。

よく使われる抽象構文木だと、全部抽象化されてわかりづらいですが、ブロックの計算、文の計算、式の計算に分かれているので、頭の中で整理しやすいです。

ちなみに今は開発が進んでいて、コードをwebassemblyとして出力するコードを書いています。
めちゃくちゃ大変ですが、まだ完成してません。

でもまあ、12月終わりまでには完成するかなと思っています。
ただ、実装したい機能が多すぎてどうするかってのは悩みですね。

お気づきかもしれませんが、C#で書いてます。これをrustかcppで書き直さないといけないと思ってます。(javascriptでもいいかもしれんけど。)

私にとって、プログラミングって得意分野でもなんでもないので、一緒に未踏に出たいという人は募集しています。

とりあえず、コンピュータ言語だけあってもしょうがないので、未踏にはプログラミング容易なExcelみたいな感じで提出しようかなと思います。
WebAssemblyの機能じゃ、グラフィカルなやつは厳しいかなと思ってます。
(この辺の話は、未踏で聞けばいいよね。)

ただ、できそうだったらやります。

AIが登場して、プログラミングのレベルがインフレしてます。
やるなら、今だと思うし、面白いアイデアには乗っかってった方が得なんじゃないかなあと思います。(私は学生の頃、動けなかったので)

一人でも、問題なくやっていくし、まあ気にしてないけど、AI時代は努力してます!が評価されなくなって、もっと上の目線をもてることが評価されるんじゃないかなあと思います。(努力がいらないわけではない。)

いずれにせよ、勝負というものはインフレしていくので、今までは大丈夫だったと考えない方がいいんじゃないかなあと思ってます。

応援してくれるとうれしいです。
スキ、フォローよろしくお願いします。


    partial class Block
    {
        public List<Line> lines = new List<Line>();
        public Line line
        {
            get { return lines[lines.Count - 1]; }
        }
        public Line pexe(Local local, Obj obj)
        {
            var i = 0;
            var last = lines.Count;
            var set = lines.Count;
            if (labelmap.ContainsKey("set"))
            {
                set = labelmap["set"].n;
            }
            if (obj == null)
            {
                if (set == 0) throw new Exception();
                else
                {
                    last = set;
                }
            }
            else
            {
                if (set >= lines.Count) throw new Exception();
                else
                {
                    i = set;
                }
            }
            var lvs = new List<Label>(labelmap.Values);
            Line before = null;
            for (; i < last; i++)
            {
                before = lines[i].exe(local, before);
                if (before.ret != null)
                {
                    if (before.ret.type == ObjType.Return) return before;
                    else if (before.ret.type == ObjType.Goto)
                    {
                        var go = before.ret as Goto;
                        if (labelmap.ContainsKey(go.value))
                        {
                            i = labelmap[go.value].n - 1;
                            continue;
                        }
                        else if (this is Local) throw new Exception();
                        else return before;
                    }
                    else if (before.ret.type == ObjType.Break || before.ret.type == ObjType.Continue)
                    {
                        return before;
                    }
                }
            }
            return before;
        }
        public Line exe(Local local, Switch switchobj)
        {
            var i = 0;
            if (switchobj != null)
            {
                if (labelmap.ContainsKey(switchobj.value))
                {
                    i = labelmap[switchobj.value].n;
                }
                else if (labelmap.ContainsKey("default"))
                {
                    i = labelmap["default"].n;
                }
                else return null;
            }
            var lvs = new List<Label>(labelmap.Values);
            Line before = null;
            for (; i < lines.Count; i++)
            {
                before = lines[i].exe(local, before);
                if (before.ret != null)
                {
                    if (before.ret.type == ObjType.Return) return before;
                    else if (before.ret.type == ObjType.Goto)
                    {
                        var go = before.ret as Goto;
                        if (labelmap.ContainsKey(go.value))
                        {
                            i = labelmap[go.value].n - 1;
                            continue;
                        }
                        else if (this is Local) throw new Exception();
                        else return before;
                    }
                    else if (before.ret.type == ObjType.Break || before.ret.type == ObjType.Continue)
                    {
                        return before;
                    }
                }
                if (switchobj != null)
                {
                    for (var j = 0; j < lvs.Count; j++)
                    {
                        if (lvs[j].n == i + 1) return before;
                    }
                }
            }
            return before;
        }
        public bool start = true;
        public bool startresult = true;
        public bool startreason = true;
        public Dictionary<String, Label> labelmap = new Dictionary<string, Label>();
    }
    class FinishException : Exception { }
    class Label
    {
        public String name;
        public int n;
        public Block block;
    }
    partial class Local : Block
    {
        public List<int> indents = new List<int>();
        public int n = 0;
        public List<Letter> letters = new List<Letter>();
        public RichTextBox console;
        public Local()
        {
            tree.block = this;
            indents.Add(0);
            blocks.Add(this);
            vtower.Add(new List<Dictionary<string, Obj>> { new Dictionary<string, Obj>() });
            var Int = new Integer() { name = "int" };
            var Print = new Print() { name = "void<-int|str" };
            var Str = new Str() { name = "Str" };
            declare("int", Int);
            declare("print", Print);
            declare("Str", Str);
            valuemapD["int"] = Int;
            valuemapD["print"] = Print;
            valuemapD["Str"] = Str;
        }
        public int indent
        {
            get { return indents[indents.Count - 1]; }
        }
        public Boolean plus(int p)
        {
            n += p;
            if (n > letters.Count) return false;
            return true;
        }
        public void label(String name)
        {
            block.labelmap[name] = new Label { name = name, n = block.lines.Count, block = block };
        }
        public Letter letter { get { return letters[n]; } }
        public bool lettersearch(LetterType[] success, LetterType[] fail)
        {
            for (var i = n; i < letters.Count; i++)
            {
                for (var j = 0; j < success.Length; j++)
                {
                    if (letters[i].type == success[j]) return true;
                }
                for (var j = 0; j < fail.Length; j++)
                {
                    if (letters[i].type == fail[j]) return false;
                }
            }
            throw new Exception();
        }
        public void feeladd(Item item)
        {
            if (block.start)
            {
                var line = new Line();
                block.lines.Add(line);
                block.line.feel = new Component();
                block.start = false;
            }
            block.line.feel.add(item);
        }
        public void feelnext()
        {
            block.line.feel.next();
        }
        public void feeldraw(Item item)
        {
            block.line.feel.draw(item);
        }
        public void resultadd(Item item)
        {
            if (block.startresult)
            {
                block.line.result = new Component();
                block.startresult = false;
            }
            block.line.result.add(item);
        }
        public void resultnext()
        {
            block.line.result.next();
        }
        public void resultdraw(Item item)
        {
            block.line.result.draw(item);
        }
        public void reasonadd(Item item)
        {
            if (block.startreason)
            {
                block.line.reason = new Component();
                block.startreason = false;
            }
            block.line.reason.add(item);
        }
        public void reasonnext()
        {
            block.line.reason.next();
        }
        public void reasondraw(Item item)
        {
            block.line.reason.draw(item);
        }
        public void NextLine()
        {
            block.start = block.startresult = block.startreason = true;
        }
        public List<Block> blocks = new List<Block>();
        public Block block
        {
            get { return blocks[blocks.Count - 1]; }
        }
        public void StartBlock(int indent)
        {
            indents.Add(indent);
            blocks.Add(block.line.block = new Block());

        }
        public void CallBlock(Call call)
        {
            blocks.Add(call.declare);
        }
        public void Call2Block(Call call)
        {
            blocks.RemoveAt(blocks.Count - 1);
            blocks.Add(call.block);
        }
        public void Call2Indent(int indent)
        {
            indents.Add(indent);
        }
        public void CallFinish()
        {
            blocks.RemoveAt(blocks.Count - 1);
        }
        public void CallIndentFinish()
        {
            indents.RemoveAt(indents.Count - 1);
        }
        public void FinishBlock()
        {
            indents.RemoveAt(indents.Count - 1);
            blocks.RemoveAt(blocks.Count - 1);
        }
        public List<List<Dictionary<String, Obj>>> vtower = new List<List<Dictionary<string, Obj>>>();
        public List<Dictionary<String, Obj>> values
        {
            get { return vtower[vtower.Count - 1]; }
            set
            {
                vtower.Add(new List<Dictionary<string, Obj>>());
                for (var i = 0; i < value.Count; i++)
                {
                    this.values.Add(value[i]);
                }
            }
        }
        public Obj get(String name)
        {
            for (var i = values.Count - 1; i >= 0; i--)
            {
                if (values[i].ContainsKey(name))
                {
                    return values[i][name];
                }
            }
            return null;
        }
        public void declare(String name, Obj obj)
        {
            var vmap = values[values.Count - 1];
            vmap[name] = obj;
        }
        public Line nextblock(Block block)
        {
            values.Add(new Dictionary<string, Obj>());
            var ret = block.exe(this, null);
            values.RemoveAt(values.Count - 1);
            return ret;
        }
        public Obj declareclass(ClassObj clsobj, Call call)
        {
            if (call == null)
            {
                clsobj.values.Add(new Dictionary<string, Obj>());
            }
            else
            {
                values = clsobj.values;
                var vmap = new Dictionary<string, Obj>();
                values.Add(vmap);
                clsobj.values.Add(vmap);
                var ret = call.declare.exe(this, null);
                clsobj.block = call.block;
                vtower.RemoveAt(vtower.Count - 1);
            }
            return clsobj;
        }
        public Obj classblock(Value value, Constructor cons, Array ar, Block block)
        {
            if (block == null) return value;
            values = cons.values;
            var keys = new List<String>(values[values.Count - 1].Keys);
            var varray = new List<Obj>(values[values.Count - 1].Values);
            var amap = new Dictionary<int, int>();
            var bmap = new Dictionary<int, int>();
            var array = new List<Label>(ar.labelmap.Values);
            for (var i = 0; i < array.Count; i++)
            {
                if (values[values.Count - 1].ContainsKey(array[i].name))
                {
                    for (var j = 0; j < keys.Count; j++)
                    {
                        if (keys[j] == array[i].name)
                        {
                            amap[array[i].n] = j;
                            bmap[j] = array[i].n;
                            varray[j].Setter(ar.objs[array[i].n].obj, this, null, ExeType.Result);
                        }
                    }
                }
                else throw new Exception();
            }
            var k = 0;
            for (var i = 0; i < ar.objs.Count; i++)
            {
                if (amap.ContainsKey(k))
                {
                    k++;
                }
                if (bmap.ContainsKey(i)) continue;
                varray[i].Setter(ar.objs[k].obj, this, null, ExeType.Result);
                k++;
            }
            values.Add(value.vmap);
            var ret = block.exe(this, null);
            vtower.RemoveAt(vtower.Count - 1);
            return value;
        }
        public Obj declarefunc(Func func, Call call)
        {
            values = func.values;
            var ret = call.declare.exe(this, null);
            var vmap = new Dictionary<string, Obj>();
            values.Add(vmap);
            func.values.Add(vmap);
            var ret2 = call.block.exe(this, null);
            vtower.RemoveAt(vtower.Count - 1);
            return func;
        }
        public Obj declarefunc2(Func func, Call call)
        {
            values = func.values;
            var vmap = new Dictionary<string, Obj>();
            values.Add(vmap);
            func.values.Add(vmap);
            var ret = call.declare.exe(this, null);
            func.block = call.block;
            vtower.RemoveAt(vtower.Count - 1);
            return func;
        }
        public Dictionary<String, Obj> callcheck(Call call)
        {
            values = new List<Dictionary<string, Obj>>();
            values.Add(new Dictionary<string, Obj>());
            var ret = call.declare.exe(this, null);
            var vals = vtower[vtower.Count - 1][0];
            vtower.RemoveAt(vtower.Count - 1);
            return vals;
        }
        public Obj funcblock(Func func, Array ar, Block block)
        {
            values = func.values;
            var keys = new List<String>(values[values.Count - 1].Keys);
            var varray = new List<Obj>(values[values.Count - 1].Values);
            var amap = new Dictionary<int, int>();
            var bmap = new Dictionary<int, int>();
            var array = new List<Label>(ar.labelmap.Values);
            for (var i = 0; i < array.Count; i++)
            {
                if (values[values.Count - 1].ContainsKey(array[i].name))
                {
                    for (var j = 0; j < keys.Count; j++)
                    {
                        if (keys[j] == array[i].name)
                        {
                            amap[array[i].n] = j;
                            bmap[j] = array[i].n;
                            varray[j].Setter(ar.objs[array[i].n].obj, this, null, ExeType.Result);
                        }
                    }
                }
                else throw new Exception();
            }
            var k = 0;
            for (var i = 0; i < ar.objs.Count; i++)
            {
                if (amap.ContainsKey(k))
                {
                    k++;
                }
                if (bmap.ContainsKey(i)) continue;
                varray[i].Setter(ar.objs[k].obj, this, null, ExeType.Result);
                k++;
            }
            var ret = func.block.exe(this, null);
            var obj = ret.ret;
            if (ret.ret.type == ObjType.Return)
            {
                obj = (ret.ret as Return).value;
            }
            if (!TypeCheck.Check(func.clsobj, obj, CheckType.Return)) throw new Exception();
            vtower.RemoveAt(vtower.Count - 1);
            return obj;
        }
        public Line switchblock(Switch switchobj, Block block)
        {
            values.Add(new Dictionary<string, Obj>());
            var ret = block.exe(this, switchobj);
            values.RemoveAt(values.Count - 1);
            return ret;
        }
        public Obj propertyblock(Property property, Obj obj)
        {
            values = property.values;
            values.Add(new Dictionary<string, Obj>());
            if (obj != null) values[values.Count - 1]["val"] = obj;
            var ret = property.block.pexe(this, obj);
            var obj2 = ret.ret;
            if (ret.ret.type == ObjType.Return)
            {
                obj2 = (ret.ret as Return).value;
            }
            if (obj == null)
            {
                if ((obj2 as Value).clsobj != property.clsobj) throw new Exception();
            }
            else
            {
                //
            }
            vtower.RemoveAt(vtower.Count - 1);
            return obj2;
        }
    }
    partial class Line
    {
        public Component feel, result, reason;
        public Obj ret;
        public Block block;
        public Obj fret;
        public Line exe(Local local, Line before)
        {
            var line = new Line();
            line.block = this.block;
            if (feel == null)
            {
                if (result == null)
                {
                    line.reason = reason.Clone();
                    line.reason.exe(local, line, ExeType.Reason);
                    line.ret = line.reason.result.Self(local, line, ExeType.Reason);
                    if (line.ret.type == ObjType.Return)
                    {
                        return line;
                    }
                    else if (line.ret.type == ObjType.Goto)
                    {
                        return line;
                    }
                    else if (line.ret.type == ObjType.Break)
                    {
                        return line;
                    }
                }
                else
                {
                    line.result = result.Clone();
                    line.fret = line.result.exe(local, line, ExeType.Result).obj;
                    if (line.fret != null)
                    {
                        if (line.fret.type == ObjType.Else)
                        {
                            if (before.fret.type == ObjType.If || before.fret.type == ObjType.Elif)
                            {
                                if (before.ret != null) return before;
                            }
                            if (block != null)
                            {
                                var ifval = line.fret as Else;
                                ifval.block = block;
                                var linret = local.nextblock(block);
                                if (linret.fret != null)
                                {
                                    if (linret.fret.type == ObjType.Return || linret.fret.type == ObjType.Goto || linret.fret.type == ObjType.Break || line.ret.type == ObjType.Continue) return linret;
                                }
                                return line;
                            }
                        }
                        else if (line.fret.type == ObjType.For)
                        {
                            var forobj = line.fret as For;
                            if (forobj.call == null) return line;
                            local.values.Add(new Dictionary<string, Obj>());
                            forobj.call.declare.exe(local, null);
                            forobj.call.block.lines[0].exe(local, forobj.call.block.lines[0]);
                        forloop:
                            Obj obj = forobj.call.block.lines[1].exe(local, forobj.call.block.lines[1]).ret;
                            var conti = false;
                        head:
                            if (obj.type == ObjType.Number)
                            {
                                var num = obj as Number;
                                if (num.num != 0) conti = true;
                            }
                            else if (obj.type == ObjType.BoolVal)
                            {
                                var bval = obj as BoolVal;
                                conti = bval.val;
                            }
                            else if (obj.type == ObjType.StrObj)
                            {
                                var str = obj as StrObj;
                                if (str.str.Length != 0) conti = true;
                            }
                            else if (obj.type == ObjType.Variable)
                            {
                                var variable = obj as Variable;
                                obj = variable.value;
                                goto head;
                            }
                            else throw new Exception();
                            if (conti)
                            {
                                if (block != null)
                                {
                                    var linret = local.nextblock(block);
                                    forobj.call.block.lines[2].exe(local, forobj.call.block.lines[2]);
                                    if (line.fret != null)
                                    {
                                        if (linret.ret.type == ObjType.Return || linret.ret.type == ObjType.Goto) return linret;
                                        else if (linret.ret.type == ObjType.Break) { }
                                        else goto forloop;
                                    }
                                }
                                else
                                {
                                    line.reason = reason.Clone();
                                    line.reason.exe(local, line, ExeType.Result);
                                    forobj.call.block.lines[2].exe(local, forobj.call.block.lines[2]);
                                    goto forloop;
                                }
                            }
                            local.values.RemoveAt(local.values.Count - 1);
                            return line;
                        }
                    }
                    if (reason != null)
                    {
                        line.reason = reason.Clone();
                        line.reason.exe(local, line, ExeType.Reason);
                        line.ret = line.result.result.obj.ResultReason(line.reason.result.obj, local, line);
                    }
                }
            }
            else
            {
                line.feel = feel.Clone();
                line.fret = line.feel.exe(local, line, ExeType.Feel).obj;
                if (line.fret.type == ObjType.Elif)
                {
                    if (before.fret.type == ObjType.If || before.fret.type == ObjType.Elif)
                    {
                        if (before.ret != null) return before;
                    }
                }
                if (result == null) throw new Exception();
                else
                {
                    line.result = result.Clone();
                    line.result.exe(local, line, ExeType.Result);
                    line.ret = line.result.result.obj = line.feel.result.obj.FeelResult(line.result.result.obj, local, line);
                    if (line.ret == null)
                    {
                        return line;
                    }
                    else if (line.ret.type == ObjType.If)
                    {
                        if (block != null)
                        {
                            var ifval = line.ret as If;
                            ifval.block = block;
                            var linret = local.nextblock(block);
                            if (linret.ret != null)
                            {
                                if (linret.ret.type == ObjType.Return || linret.ret.type == ObjType.Goto || linret.ret.type == ObjType.Break || line.ret.type == ObjType.Continue) return linret;
                            }
                            return line;
                        }
                    }
                    else if (line.ret.type == ObjType.Elif)
                    {
                        if (block != null)
                        {
                            var ifval = line.ret as Elif;
                            ifval.block = block;
                            var linret = local.nextblock(block);
                            if (linret.fret != null)
                            {
                                if (linret.ret.type == ObjType.Return || linret.ret.type == ObjType.Goto || linret.ret.type == ObjType.Break || line.ret.type == ObjType.Continue) return linret;
                            }
                            return line;
                        }
                    }
                    else if (line.ret.type == ObjType.Switch)
                    {
                        var switchobj = line.ret as Switch;
                        var linret = local.switchblock(switchobj, block);
                        if (linret.fret != null)
                        {
                            if (linret.ret.type == ObjType.Return || linret.ret.type == ObjType.Goto || linret.ret.type == ObjType.Break || line.ret.type == ObjType.Continue) return linret;
                        }
                        return line;
                    }
                    else if (line.ret.type == ObjType.While)
                    {
                        for (; ; )
                        {
                            if (block != null)
                            {
                                var linret = local.nextblock(block);
                                if (linret.ret != null)
                                {
                                    if (linret.ret.type == ObjType.Return || linret.ret.type == ObjType.Goto) return linret;
                                    else if (linret.ret.type == ObjType.Break) break;
                                }
                            }
                            else
                            {
                                line.reason = reason.Clone();
                                line.reason.exe(local, line, ExeType.Result);
                            }
                            line.result = result.Clone();
                            line.result.exe(local, line, ExeType.Result);
                            line.ret = line.result.result.obj = line.feel.result.obj.FeelResult(line.result.result.obj, local, line);
                            if (line.ret == null || line.ret.type != ObjType.While) return line;
                        }
                    }
                    else if (line.fret.type == ObjType.For)
                    {
                        var forobj = line.fret as For;
                        if (forobj.extend.type == ObjType.Block || forobj.extend.type == ObjType.Array)
                        {
                            var ar = forobj.extend as Array;
                            if (forobj.variables.Count == 1)
                            {
                                for (var i = 0; i < ar.objs.Count; i++)
                                {
                                    forobj.variables[0].Setter(ar.objs[i].obj, local, line, ExeType.Result);
                                    if (block != null)
                                    {
                                        var linret = local.nextblock(block);
                                        if (linret.fret != null)
                                        {
                                            if (linret.ret.type == ObjType.Return || linret.ret.type == ObjType.Goto) return linret;
                                            else if (linret.ret.type == ObjType.Break) break;
                                        }
                                    }
                                    else
                                    {
                                        line.reason = reason.Clone();
                                        line.reason.exe(local, line, ExeType.Result);
                                    }
                                }
                                return line;
                            }
                            else if (forobj.variables.Count > 0)
                            {
                                for (var i = 0; i < ar.objs.Count; i++)
                                {
                                    if (ar.objs[i].obj.type == ObjType.Block || ar.objs[i].obj.type == ObjType.Array)
                                    {
                                        var ar2 = ar.objs[i].obj as Array;
                                        for (var j = 0; j < forobj.variables.Count; j++)
                                        {
                                            forobj.variables[j].Setter(ar2.objs[j].obj, local, line, ExeType.Result);
                                            if (block != null)
                                            {
                                                var linret = local.nextblock(block);
                                                if (linret.ret != null)
                                                {
                                                    if (linret.ret.type == ObjType.Return || linret.ret.type == ObjType.Goto) return linret;
                                                    else if (linret.ret.type == ObjType.Break) break;
                                                }
                                            }
                                            else
                                            {
                                                line.reason = reason.Clone();
                                                line.reason.exe(local, line, ExeType.Result);
                                            }
                                        }
                                    }
                                    else throw new Exception();
                                }
                                return line;
                            }
                            throw new Exception();
                        }
                    }
                    if (reason != null)
                    {
                        line.reason = reason.Clone();
                        line.reason.exe(local, line, ExeType.Reason);
                        line.ret = line.result.result.obj.ResultReason(line.reason.result.obj, local, line);
                        if (line.ret.type == ObjType.Return)
                        {
                            return line;
                        }
                        else if (line.ret.type == ObjType.Goto)
                        {
                            return line;
                        }
                        else if (line.ret.type == ObjType.Break)
                        {
                            return line;
                        }
                    }
                }
            }
            return line;
        }
    }
    enum ExeType
    {
        Feel, Result, Reason
    }
    partial class Component
    {
        public Item item;
        public List<Item>[] opes = new List<Item>[20];
        public bool arrayed = false;
        public Item result;
        public Component()
        {
            for (var i = 0; i < opes.Length; i++) opes[i] = new List<Item>();
        }
        public void add(Item item)
        {
            if (arrayed)
            {
                var ar = this.item.obj as Array;
                ar.add(item);
            }
            else
            {
                if (this.item == null)
                {
                    this.item = item;
                    if (item.order >= 0) opes[item.order].Add(item);
                }
                else
                {
                    this.item.Add(item);
                    this.item = item;
                    if (item.order >= 0) opes[item.order].Add(item);
                }
            }
        }
        public void next()
        {
            if (arrayed)
            {
                var ar = this.item.obj as Array;
                ar.next();
            }
            else
            {
                var ar = new Array();
                ar.objs.Add(this.item);
                ar.opess.Add(opes);
                this.item = new Item(LetterType.Array) { obj = ar };
                this.opes = new List<Item>[0];
                arrayed = true;
            }
        }
        public Item exe(Local local, Line line, ExeType type)
        {
            Item item = null;
            for (var i = 0; i < opes.Length; i++)
            {
                if (opes[i] == null) continue;
                for (var j = 0; j < opes[i].Count; j++)
                {
                    if (i == 0)
                    {
                        opes[i][j].obj = opes[i][j].Self(local, line, type);
                    }
                    else item = opes[i][j].Ope(local, line, type);
                }
            }
            if (item == null)
            {
                this.item.Self(local, line, type);
                if (type == ExeType.Feel || type == ExeType.Reason) this.item.obj = this.item.obj.Getter(local, line, type);
                else
                {
                    //if (line.feel != null && line.feel.ret.obj.type == ObjType.If)
                }
                this.result = this.item;
                return this.item;
            }
            this.result = item;
            return item;
        }
        public void draw(Item item)
        {
            if (arrayed)
            {
                var ar = this.item.obj as Array;
                ar.addfunc(item);
            }
            else
            {
                this.item.draws.Add(item);
            }

        }
        public Component Clone()
        {
            var comp = new Component();
            var start = item;
            for (var i = start; ; i = i.next)
            {
                comp.add(i.Clone);
                if (i.next == start) break;
            }
            return comp;
        }
        public void Finish()
        {
            item = item.next;
        }
    }
    partial class Item
    {
        public Item next, before;
        public LetterType type;
        public String name;
        public Obj obj;
        public int order = -1;
        public List<Item> draws = new List<Item>();
        public Item(LetterType type)
        {
            this.type = type;
            next = before = this;
        }
        public virtual Obj Self(Local local, Line line, ExeType type)
        {
            this.obj = this.obj.Self(local, line, type);
            for (var i = 0; i < draws.Count; i++)
            {
                this.obj = this.obj.Getter(local, line, type);
                if (draws[i].obj.type == ObjType.Block)
                {
                    var ar = (draws[i].obj.Self(local, line, type)) as Array;
                    this.obj = this.obj.Draw(ar, local, line, type);
                }
                else if (draws[i].obj.type == ObjType.Call)
                {
                    var call = (draws[i].obj.Self(local, line, type)) as Call;
                    this.obj = this.obj.Call(call, local, line, type);
                }
            }
            draws = new List<Item>();
            return this.obj;
        }
        public void Add(Item item)
        {
            item.next = next;
            next.before = item;
            next = item;
            item.before = this;
        }
        public Item Ope(Local local, Line line, ExeType type)
        {
            var val1 = this.before;
            var val2 = this.next;
            var ope = this;
            var ret = val1.OpeExe(val2, ope, local, line, type);
            switch (ope.type) {
                case LetterType.SingleMinus:
                    val1.next = ret;
                    ret.before = val1;
                    break;
                default:
                    val1.before.next = ret;
                    ret.before = val1.before;
                    break;
            }
            val2.next.before = ret;
            ret.next = val2.next;
            return ret;
        }
        public Item OpeExe(Item val2, Item ope, Local local, Line line, ExeType type)
        {
            if (ope.type == LetterType.SingleMinus)
            {
                var objk = val2.Self(local, line, type).Getter(local, line, type);
                var objl = val2.obj.SingleMinus(local, line, type);
                return new Item(LetterType.Value) { obj = objl };
            }
            var obj = this.Self(local, line, type).Getter(local, line, type);
            switch (ope.type)
            {
                case LetterType.Plus:
                    var obj2 = val2.Self(local, line, type).Getter(local, line, type);
                    var obj6 = this.obj.Plus(obj2, local, line, type);
                    return new Item(LetterType.Value) { obj = obj6 };
                case LetterType.Minus:
                    var obj3 = val2.Self(local, line, type).Getter(local, line, type);
                    var obj5 = this.obj.Minus(obj3, local, line, type);
                    return new Item(LetterType.Value) { obj = obj5 };
                case LetterType.Mul:
                    var obj11 = val2.Self(local, line, type).Getter(local, line, type);
                    var obj12 = this.obj.Mul(obj11, local, line, type);
                    return new Item(LetterType.Value) { obj = obj12 };
                case LetterType.Div:
                    var obj21 = val2.Self(local, line, type).Getter(local, line, type);
                    var obj22 = this.obj.Div(obj21, local, line, type);
                    return new Item(LetterType.Value) { obj = obj22 };
                case LetterType.EqualEqual:
                    var obji = val2.Self(local, line, type).Getter(local, line, type);
                    var objj = this.obj.EqualEqual(obji, local, line, type);
                    return new Item(LetterType.Value) { obj = objj };
                case LetterType.LessThan:
                    var obja = val2.Self(local, line, type).Getter(local, line, type);
                    var objb = this.obj.LessThan(obja, local, line, type);
                    return new Item(LetterType.Value) { obj = objb };
                case LetterType.MoreThan:
                    var objc = val2.Self(local, line, type).Getter(local, line, type);
                    var objd = this.obj.MoreThan(objc, local, line, type);
                    return new Item(LetterType.Value) { obj = objd };
                case LetterType.LessEqual:
                    var obje = val2.Self(local, line, type).Getter(local, line, type);
                    var objf = this.obj.LessEqual(obje, local, line, type);
                    return new Item(LetterType.Value) { obj = objf };
                case LetterType.MoreEqual:
                    var objg = val2.Self(local, line, type).Getter(local, line, type);
                    var objh = this.obj.MoreEqual(objg, local, line, type);
                    return new Item(LetterType.Value) { obj = objh };
                case LetterType.Dot:
                    val2.obj = this.obj.Dot(val2.obj, local, line, type);
                    if (type == ExeType.Feel || type == ExeType.Reason) val2.obj = val2.obj.Getter(local, line, type);
                    else
                    {
                        //if (line.feel != null && line.feel.ret.obj.type == ObjType.If)
                    }
                    var obj4 = val2.Self(local, line, type);
                    return new Item(LetterType.Value) { obj = obj4 };
                case LetterType.Left:
                    val2.obj = this.obj.Left(val2, local, line, type);
                    var obj7 = val2.Self(local, line, type);
                    return new Item(LetterType.Value) { obj = obj7 };
            }
            throw new Exception();
        }
        public virtual Item Minus(Item val2)
        {
            throw new NotImplementedException();
        }
        public virtual Item Clone
        {
            get
            {
                Obj obj = null;
                if (this.obj != null) obj = this.obj.Clone;
                return new Item(this.type) { order = this.order, obj = obj, draws = draws, name = name };
            }
        }
        public Item Letter(Local local)
        {
            switch (name)
            {
                case "private":
                    obj = new Private();
                    break;
                case "public":
                    obj = new Public();
                    break;
                case "internal":
                    obj = new Internal();
                    break;
                case "class":
                    obj = new Class();
                    break;
                case "var":
                    obj = new Var();
                    break;
                case "if":
                    obj = new If();
                    break;
                case "elif":
                    obj = new Elif();
                    break;
                case "else":
                    obj = new Else();
                    break;
                case "return":
                    obj = new Return();
                    break;
                case "goto":
                    obj = new Goto();
                    break;
                case "while":
                    obj = new While();
                    break;
                case "for":
                    obj = new For();
                    break;
                case "break":
                    obj = new Break();
                    break;
                case "continue":
                    obj = new Continue();
                    break;
                case "switch":
                    obj = new Switch();
                    break;
                case "true":
                    obj = new BoolVal(true, local.get("bool"));
                    break;
                case "false":
                    obj = new BoolVal(false, local.get("bool"));
                    break;
                case "null":
                    obj = new Null();
                    break;
                default:
                    obj = new Word(name);
                    break;
            }
            return this;
        }
        public Item Number(Local local)
        {

            obj = new Number(Convert.ToInt32(name), local.get("int"));
            return this;
        }
        public Item StrObj(Local local)
        {
            obj = new StrObj(name, local.get("Str"));
            return this;
        }
    }
    enum ObjType
    {
        Optional, ClassObj, Function, Value, Class, Block, Word, Var, Type, Number, Variable, VoiVal, If, Call, Elif, Else, Return, Goto, Str, StrObj, While, For, Break, Continue, BoolVal, Switch, ArrayVal, Property, Null, Array, NoFound
    }
    enum Accesor
    {
        Private, Public, Internal, Single
    }
    class Optional : Obj
    {
        public Accesor accesor = Accesor.Private;
        public Optional() : base(ObjType.Optional) { }
        public override Obj Plus(Obj val2, Local local, Line line, ExeType type)
        {
            throw new Exception();
        }
        public override Obj Minus(Obj val2, Local local, Line line, ExeType type)
        {
            if (type != ExeType.Feel) throw new Exception();
            var obj = val2;
            if (obj.type == ObjType.Optional)
            {
                var v2 = obj as Optional;
                return new Optional() { accesor = v2.accesor };
            }
            else if (obj.type == ObjType.Class)
            {
                return new Class() { accesor = this.accesor };
            }
            else if (obj.type == ObjType.Var)
            {
                return new Var() { accesor = this.accesor };
            }
            else if (obj.type == ObjType.Word)
            {
                var type2 = new Type(local.get((obj as Word).name) as ClassObj) { accesor = this.accesor };
                return type2;
            }
            else if (obj.type == ObjType.ClassObj)
            {
                var type2 = new Type(local.get((obj as Word).name) as ClassObj) { accesor = this.accesor };
                return type2;
            }
            throw new Exception();
        }
        public override Obj Dot(Obj val2, Local local, Line line, ExeType type)
        {
            throw new Exception();
        }
        public override Obj Self(Local local, Line line, ExeType type)
        {
            return this;
        }
        public override Obj Setter(Obj obj, Local local, Line line, ExeType type)
        {
            throw new Exception();
        }
    }
    class Private : Optional
    {
        public Private() : base()
        {
        }
        public override Obj Clone
        {
            get { return new Private(); }
        }
    }
    class Public : Optional
    {
        public Public() : base()
        {
            accesor = Accesor.Public;
        }
        public override Obj Clone
        {
            get { return new Public(); }
        }
    }
    class Internal : Optional
    {
        public Internal() : base()
        {
            accesor = Accesor.Internal;
        }
        public override Obj Clone
        {
            get { return new Internal(); }
        }
    }
    class Letter
    {
        public String name;
        public LetterType type;
        public int indent;
        public int row;
    }
    enum LetterType
    {
        Letter, AtLetter, Symbol, Number, Colon, Comma, Kaigyou, Dot, BracketS, BracketE, BlockS, BlockE, Call,
        Class, If, For, Elif, Else, End, Bou, BraceS, BraceE, Right, Left, Semicolon, Sharp, Str,
        Value, Func, ClassObj, Array,
        Plus, Minus, Mul, Div, LessThan, MoreThan, LessEqual, MoreEqual, EqualEqual, Operator,
        SingleMinus,
    }
    enum CheckType
    {

        Setter, Return
    }
    partial class TypeCheck
    {
        public static bool Check(Obj clsobj, Obj val, CheckType type)
        {
            Obj v = val;
            if (v.type == ObjType.Variable)
            {
                var variable = v as Variable;
                v = variable.value;
            }
            Var vari = null;
            Type typ = null;
        head:
            if (clsobj.type == ObjType.Class)
            {
                if (v.type == ObjType.ClassObj) return true;
                else if (v.type == ObjType.Null) return true;
                throw new Exception();
            }
            else if (clsobj.type == ObjType.ClassObj)
            {
                if (clsobj is Void)
                {
                    if (type == CheckType.Return) return true;
                    else throw new Exception();
                }
                var cls = clsobj as ClassObj;
                if (v.type == ObjType.Number || v.type == ObjType.BoolVal || v.type == ObjType.StrObj || v.type == ObjType.Value)
                {
                    var value = v as Value;
                    if (vari == null)
                    {
                        for (ClassObj i = value.clsobj as ClassObj; i != null; i = i.extend)
                        {
                            if (value.clsobj == cls) return true;
                        }
                    }
                    else
                    {
                        var clsar = new List<ClassObj>();
                        for (ClassObj i = value.clsobj as ClassObj; i != null; i = i.extend)
                        {
                            for (ClassObj j = cls; j != null; j = j.extend)
                            {
                                if (value.clsobj == j)
                                {
                                    if (typ == null)
                                    {
                                        vari.clsobj = j;
                                    }
                                    else
                                    {
                                        typ.clsobj = j;
                                    }
                                    return true;
                                }
                            }
                        }
                    }
                    throw new Exception();
                }
                else if (v.type == ObjType.Null) return true;
                throw new Exception();
            }
            else if (clsobj.type == ObjType.Type)
            {
                var typeobj = clsobj as Type;
                if (v.type == ObjType.Null) return true;
                for (var i = typeobj.array - 1; i >= 0; i--)
                {
                    if (v.type == ObjType.Block)
                    {
                        BlockToArray(v as Array);
                    }
                    if (v.type == ObjType.Array) {
                        var ar = v as Array;
                        if (ar.objs.Count == 0) break;
                        else v = ar.objs[0].obj;
                        continue;
                    }
                    else if (v.type == ObjType.Null) break;
                }
                if (typeobj.draws.Count == 0)
                {
                    clsobj = typeobj.clsobj;
                    typ = typeobj;
                    goto head;
                }
                else
                {
                    if (v.type == ObjType.Function)
                    {
                        var func = v as Func;
                        var varray = new List<Obj>(func.values[func.values.Count - 1].Values);
                        var ret = false;
                        for (var i = 0; i < typeobj.draws.Count; i++)
                        {
                            if (varray[i].type == ObjType.Variable)
                            {
                                ret = TypeTypeCheck(typeobj.draws[i], (varray[i] as Variable).clsobj, vari, delegate (Obj obj)
                                {
                                    typeobj.draws[i] = obj;
                                });
                                if (!ret) throw new Exception();
                            }
                        }
                        var ret2 = TypeTypeCheck(typeobj.clsobj, func.clsobj, vari, delegate (Obj obj)
                        {
                            typeobj.clsobj = obj;
                        });
                        if (!ret2) throw new Exception();
                        return true;
                    }
                    else throw new Exception();
                }

            }
            else if (clsobj.type == ObjType.Var)
            {
                var varobj = clsobj as Var;
                if (varobj.clsobj != null) { clsobj = varobj.clsobj; goto head; }
                Type ty = null;
            head2:
                if (v.type == ObjType.Block)
                {
                    BlockToArray(v as Array);
                }
                if (v.type == ObjType.Array) {
                    if (ty == null) ty = new Type(new Var());
                    ty.array++;
                    var ar = v as Array;
                    if (ar.objs.Count == 0)
                    {
                        varobj.clsobj = ty;
                    }
                    else
                    {
                        v = ar.objs[0].obj;
                        goto head2;
                    }
                    return true;
                }
                else if (v.type == ObjType.StrObj || v.type == ObjType.Number || v.type == ObjType.BoolVal || v.type == ObjType.Null)
                {
                    if (ty == null) varobj.clsobj = (v as Value).clsobj;
                    else ty.clsobj = (v as Value).clsobj;
                    return true;
                }
                else if (v.type == ObjType.Value)
                {
                    var value = v as Value;
                    if (ty == null) varobj.clsobj = value.clsobj;
                    else ty.clsobj = value.clsobj;
                    return true;
                }
                else if (v.type == ObjType.ClassObj)
                {
                    varobj.clsobj = new Class();
                    return true;
                }
                else if (v.type == ObjType.Function)
                {
                    var typeobj = new Type(new Var());
                    var func = v as Func;
                    var varray = new List<Obj>(func.values[func.values.Count - 1].Values);
                    for (var i = 0; i < varray.Count; i++)
                    {
                        if (varray[i].type == ObjType.Variable)
                        {
                            var variable = varray[i] as Variable;
                            typeobj.draws.Add(variable.clsobj);
                        }
                    }
                    typeobj.clsobj = func.clsobj;
                    if (ty == null) varobj.clsobj = typeobj;
                    else ty.clsobj = typeobj;
                    return true;
                }
                else if (v.type == ObjType.Null)
                {
                    return true;
                }
            }
            throw new Exception();
        }
        public static void BlockToArray(Array ar)
        {
            ar.type = ObjType.Array;
            for (var i = 0; i < ar.objs.Count; i++)
            {
                if (ar.objs[i].obj.type == ObjType.Block)
                {
                    BlockToArray(ar.objs[i].obj as Array);
                }
            }
        }
        public static bool TypeTypeCheck(Obj clsobj, Obj funccls, Var vari, Action<Obj> act)
        {
            Var vari2 = null;
        head:
            if (clsobj.type == ObjType.Var)
            {
                var variable = clsobj as Var;
                if (variable.clsobj != null)
                {
                    clsobj = variable;
                    vari2 = variable;
                    goto head;
                }
            }
            if (funccls.type == ObjType.Var)
            {
                var varobj = funccls as Var;
                if (clsobj.type == ObjType.Var) return true;
                varobj.clsobj = clsobj;
                return true;
            }
            else if (funccls.type == ObjType.Class)
            {
                if (clsobj.type == ObjType.Class) return true;
                else if (clsobj.type == ObjType.Var)
                {
                    var various = clsobj as Var;
                    various.clsobj = funccls;
                    return true;
                }
                else throw new Exception();
            }
            else if (funccls.type == ObjType.ClassObj)
            {
                if (clsobj.type == ObjType.ClassObj)
                {
                    if (vari == null && vari2 == null)
                    {
                        var cls = clsobj as ClassObj;
                        for (ClassObj i = funccls as ClassObj; i != null; i = i.extend)
                        {
                            if (funccls == cls) return true;
                        }
                    }
                    else
                    {
                        var cls = clsobj as ClassObj;
                        for (ClassObj i = funccls as ClassObj; i != null; i = i.extend)
                        {
                            for (ClassObj j = cls; j != null; j = j.extend)
                            {
                                if (vari2 != null)
                                {
                                    vari2.clsobj = j;
                                    return true;
                                }
                                else if (i == j)
                                {
                                    act(j);
                                    return true;
                                }
                            }
                        }
                    }
                    throw new Exception();
                }
                else if (clsobj.type == ObjType.Var)
                {
                    var various = clsobj as Var;
                    various.clsobj = funccls;
                    return true;
                }
            }
            else if (funccls.type == ObjType.Type)
            {
                var typeval = funccls as Type;
                if (clsobj.type == ObjType.Type)
                {
                    var typeobj2 = clsobj as Type;
                    if (typeval.array != typeobj2.array) throw new Exception();
                    if (typeval.draws.Count != typeobj2.draws.Count) throw new Exception();
                    for (var i = 0; i < typeobj2.draws.Count; i++)
                    {
                        var ret = TypeTypeCheck(typeobj2.draws[i], typeval.draws[i], vari, delegate (Obj obj)
                        {
                            typeobj2.draws[i] = obj;
                        });
                        if (!ret) throw new Exception();
                    }
                    bool ret2 = false;
                    if (vari != null)
                    {
                        ret2 = TypeTypeCheck(typeobj2.clsobj, typeval.clsobj, vari, delegate (Obj obj)
                        {
                            typeobj2.clsobj = obj;
                        });
                    }
                    else if (vari2 != null)
                    {
                        ret2 = TypeTypeCheck(typeobj2.clsobj, typeval.clsobj, vari2, delegate (Obj obj)
                        {
                            typeobj2.clsobj = obj;
                        });
                    }
                    if (!ret2) throw new Exception();
                }
                else if (clsobj.type == ObjType.Var)
                {
                    var various = clsobj as Var;
                    various.clsobj = funccls;
                    return true;
                }
                throw new Exception();
            }
            else if (funccls.type == ObjType.Var)
            {
                var varval = funccls as Var;
                if (clsobj.type == ObjType.Var) return true;
                else
                {
                    varval.clsobj = clsobj;
                    return true;
                }
            }
            throw new Exception();
        }
    }
partial class Obj
    {
        public ObjType type;
        public Obj(ObjType type)
        {
            this.type = type;
        }

        public virtual Obj Self(Local local, Line line, ExeType type)
        {
            return this;
        }

        public virtual Obj Getter(Local local, Line line, ExeType type)
        {
            return this;
        }
        public virtual Obj Setter(Obj obj, Local local, Line line, ExeType type)
        {
            throw new Exception();
        }
        public virtual Obj SingleMinus(Local local, Line line, ExeType type)
        {
            throw new Exception();
        }
        public virtual Obj Plus(Obj val2, Local local, Line line, ExeType type)
        {
            throw new Exception();
        }
        public virtual Obj Minus(Obj val2, Local local, Line line, ExeType type)
        {
            throw new Exception();
        }
        public virtual Obj Mul(Obj val2, Local local, Line line, ExeType type)
        {
            throw new Exception();
        }
        public virtual Obj Div(Obj val2, Local local, Line line, ExeType type)
        {
            throw new Exception();
        }
        public virtual Obj EqualEqual(Obj val2, Local local, Line line, ExeType type)
        {
            throw new Exception();
        }
        public virtual Obj LessThan(Obj val2, Local local, Line line, ExeType type)
        {
            throw new Exception();
        }
        public virtual Obj MoreThan(Obj val2, Local local, Line line, ExeType type)
        {
            throw new Exception();
        }
        public virtual Obj LessEqual(Obj val2, Local local, Line line, ExeType type)
        {
            throw new Exception();
        }
        public virtual Obj MoreEqual(Obj val2, Local local, Line line, ExeType type)
        {
            throw new Exception();
        }
        public virtual Obj Dot(Obj val2, Local local, Line line, ExeType type)
        {
            throw new Exception();
        }
        public virtual Obj Left(Item val2, Local local, Line line, ExeType type)
        {
            throw new Exception();
        }
        public virtual Obj Clone
        {
            get
            {
                throw new Exception();
            }
        }
        public virtual Obj Draw(Array ar, Local local, Line line, ExeType type)
        {
            throw new Exception();
        }
        public virtual Obj Call(Call call, Local local, Line line, ExeType type)
        {
            throw new Exception();
        }
        public virtual Obj FeelResult(Obj val2, Local local, Line line)
        {
            throw new Exception();
        }
        public virtual Obj ResultReason(Obj val2, Local local, Line line)
        {
            throw new Exception();
        }
    }
    partial class Class : Obj
    {
        public Accesor accesor = Accesor.Private;
        public Obj extend;
        public Class() : base(ObjType.Class)
        {
        }
        public override Obj FeelResult(Obj val2, Local local, Line line)
        {
            if (val2.type == ObjType.Block)
            {
                var ar = val2 as Array;
                var clsobjs = new List<Item>();
                for (var i = 0; i < ar.objs.Count; i++)
                {
                    if (ar.objs[i].obj.type == ObjType.Word)
                    {
                        var word = ar.objs[i].obj as Word;
                        var clsobj = new ClassObj();
                        clsobj.Extend(word.extend);
                        clsobj.Block(local.values);
                        var variable = new Variable(word.name, this) { value = clsobj };
                        local.declare(word.name, variable);
                        local.declareclass(clsobj, word.call);
                        clsobjs.Add(new Item(LetterType.ClassObj) { obj = variable });
                    }
                    else throw new Exception();
                }
                return new Array() { objs = clsobjs };

            }
            else if (val2.type == ObjType.Word)
            {

                var word = val2 as Word;
                var clsobj = new ClassObj();
                clsobj.Extend(word.extend);
                clsobj.Block(local.values);
                var variable = new Variable(word.name, this) { value = clsobj };
                local.declare(word.name, variable);
                local.declareclass(clsobj, word.call);
                return variable;
            }
            else throw new Exception();
        }
        public override Obj Left(Item val2, Local local, Line line, ExeType type)
        {
            var obj = val2.obj.Self(local, line, type);
            return new Class() { extend = obj };
        }
        public override Obj Call(Call call, Local local, Line line, ExeType type)
        {
            var clsobj = new ClassObj();
            clsobj.Extend(extend);
            clsobj.Block(local.values);
            local.declareclass(clsobj, call);
            return clsobj;
        }
        public override Obj Clone
        {
            get { return new Class(); }
        }
    }
    partial class Var : Obj
    {
        public Obj clsobj;
        public Accesor accesor = Accesor.Private;
        public Var() : base(ObjType.Var)
        {
        }
        public override Obj FeelResult(Obj val2, Local local, Line line)
        {
            if (val2.type == ObjType.Block)
            {
                var ar = val2 as Array;
                var rets = new List<Item>();
                for (var i = 0; i < ar.objs.Count; i++)
                {
                    if (ar.objs[i].obj.type == ObjType.Word)
                    {
                        var word = ar.objs[i].obj as Word;
                        if (word.call == null)
                        {
                            if (line.block == null)
                            {
                                var value = new Variable(word.name, this);
                                local.declare(word.name, value);
                                rets.Add(new Item(LetterType.Value) { obj = value });
                            }
                            else
                            {
                                var property = new Property(this, line.block);
                                property.Block(local.values);
                                local.declare(word.name, property);
                                rets.Add(new Item(LetterType.Value) { obj = property });
                            }
                        }
                        else
                        {
                            var type = new Type(this);
                            var func = new Func(this, word.call);
                            func.Block(local.values);
                            local.declarefunc2(func, func.call);
                            var variable = new Variable(word.name, this) { value = func };
                            local.declare(word.name, variable);
                            var varray = new List<Obj>(func.values[func.values.Count - 1].Values);
                            for (var j = 0; j < varray.Count; j++) type.draws.Add((varray[j] as Variable).clsobj);
                            rets.Add(new Item(LetterType.Func) { obj = variable });
                        }
                    }
                    else throw new Exception();
                }
                return new Array() { objs = rets };

            }
            else if (val2.type == ObjType.Word)
            {

                var word = val2 as Word;
                if (word.call == null)
                {
                    if (line.block == null)
                    {
                        var value = new Variable(word.name, this);
                        local.declare(word.name, value);
                        return value;
                    }
                    else
                    {
                        var property = new Property(this, line.block);
                        property.Block(local.values);
                        local.declare(word.name, property);
                        return property;
                    }
                }
                else
                {
                    var func = new Func(this, word.call);
                    func.Block(local.values);
                    local.declarefunc2(func, func.call);
                    var variable = new Variable(word.name, this) { value = func };
                    local.declare(word.name, variable);
                    return variable;
                }
            }
            else throw new Exception();
        }
        public override Obj Clone
        {
            get { return new Var(); }
        }
    }
    partial class Word : Obj
    {
        public String name;
        public Obj extend;
        public Call call;
        public Word(String name) : base(ObjType.Word)
        {
            this.name = name;
        }
        public override Obj Dot(Obj val2, Local local, Line line, ExeType type)
        {
            var obj = local.get(name);
            return obj.Dot(val2, local, line, type);
        }
        public override Obj Left(Item val2, Local local, Line line, ExeType type)
        {
            var obj2 = val2.obj;
        head:
            if (obj2.type == ObjType.Word)
            {
                var word = obj2 as Word;
                obj2 = local.get(word.name);
                goto head;
            }
            else if (obj2.type == ObjType.Variable)
            {
                var variable = obj2 as Variable;
                obj2 = variable.value;
                goto head;
            }
            else if (obj2.type == ObjType.ClassObj)
            {
                this.extend = obj2;
            }
            else if (obj2.type == ObjType.Block)
            {
                this.extend = obj2;
            }
            else throw new Exception();
            return this;
        }
        public override Obj Self(Local local, Line line, ExeType type)
        {
            if (line.feel != null && type == ExeType.Result)
            {
                Obj obj = line.feel.result.obj;
            head:
                switch (obj.type)
                {
                    case ObjType.Word:
                        obj = local.get((obj as Word).name);
                        goto head;
                    case ObjType.ClassObj:
                    case ObjType.Type:
                    case ObjType.Class:
                    case ObjType.Var:
                    case ObjType.For:
                        return this;
                }
            }
            return local.get(name);
        }
        public override Obj Draw(Array ar, Local local, Line line, ExeType type)
        {
            return local.get(name).Draw(ar, local, line, type);
        }
        public override Obj Call(Call call, Local local, Line line, ExeType type)
        {
            this.call = call;
            return this;
        }
        public override Obj FeelResult(Obj val2, Local local, Line line)
        {
            var obj = Self(local, line, ExeType.Feel);
            return obj.FeelResult(val2, local, line);
        }
        public override Obj Clone
        {
            get { return new Word(name); }
        }
    }
    partial class Array : Obj
    {
        public ClassObj cls = null;
        public List<List<Item>[]> opess = new List<List<Item>[]>();
        public Dictionary<String, Label> labelmap = new Dictionary<string, Label>();
        public Obj extend;
        public Array() : base(ObjType.Block)
        {

        }
        public override Obj Plus(Obj val2, Local local, Line line, ExeType type)
        {
            if (objs.Count == 1) return objs[0].obj.Plus(val2, local, line, type);
            throw new Exception();

        }
        public override Obj Minus(Obj val2, Local local, Line line, ExeType type)
        {
            if (objs.Count == 1) return objs[0].obj.Minus(val2, local, line, type);
            throw new Exception();
        }
        public override Obj Mul(Obj val2, Local local, Line line, ExeType type)
        {
            if (objs.Count == 1) return objs[0].obj.Mul(val2, local, line, type);
            throw new Exception();
        }
        public override Obj Div(Obj val2, Local local, Line line, ExeType type)
        {
            if (objs.Count == 1) return objs[0].obj.Div(val2, local, line, type);
            throw new Exception();
        }
        public override Obj EqualEqual(Obj val2, Local local, Line line, ExeType type)
        {
            if (objs.Count == 1) return objs[0].obj.EqualEqual(val2, local, line, type);
            throw new Exception();
        }
        public override Obj MoreThan(Obj val2, Local local, Line line, ExeType type)
        {
            if (objs.Count == 1) return objs[0].obj.MoreThan(val2, local, line, type);
            throw new Exception();
        }
        public override Obj LessThan(Obj val2, Local local, Line line, ExeType type)
        {
            if (objs.Count == 1) return objs[0].obj.LessThan(val2, local, line, type);
            throw new Exception();
        }
        public override Obj MoreEqual(Obj val2, Local local, Line line, ExeType type)
        {
            if (objs.Count == 1) return objs[0].obj.MoreEqual(val2, local, line, type);
            throw new Exception();
        }
        public override Obj LessEqual(Obj val2, Local local, Line line, ExeType type)
        {
            if (objs.Count == 1) return objs[0].obj.LessEqual(val2, local, line, type);
            throw new Exception();
        }
        public override Obj Setter(Obj obj, Local local, Line line, ExeType type)
        {
            if (obj.type == ObjType.Block || obj.type == ObjType.Array)
            {
                var ar = obj as Array;
                for (var i = 0; i < objs.Count; i++)
                {
                    objs[i].obj.Setter(ar.objs[i % ar.objs.Count].obj, local, line, type);
                }
                return this;
            }
            else if (obj.type == ObjType.Variable)
            {
                var variable = obj as Variable;
                for (var i = 0; i < objs.Count; i++)
                {
                    objs[i].obj.Setter(variable.value, local, line, type);
                }
                return this;
            }
            else throw new Exception();
        }
        public List<Item> objs = new List<Item>();
        public Item obj
        {
            get { return objs[objs.Count - 1]; }
        }
        bool start = true;
        Item ins = null;
        public void label(String name)
        {
            labelmap[name] = new Label { name = name, n = objs.Count, block = null };
        }
        public void add(Item item)
        {
            if (start)
            {
                objs.Add(item);
                opess.Add(new List<Item>[20]);
                for (var i = 0; i < 20; i++) opess[objs.Count - 1][i] = new List<Item>();
                if (item.order >= 0) opess[objs.Count - 1][item.order].Add(item);
                start = false;
                ins = item;
            }
            else
            {
                if (item.order >= 0) opess[objs.Count - 1][item.order].Add(item);
                ins.Add(item);
                ins = item;
            }
        }
        public void addfunc(Item item)
        {
            ins.draws.Add(item);
        }
        public void next()
        {
            start = true;
        }
        public override Obj FeelResult(Obj val2, Local local, Line line)
        {
            if (val2.type == ObjType.Block)
            {
                var ar = val2 as Array;
                var values = new List<Item>();
                for (var i = 0; i < ar.objs.Count; i++)
                {
                    if (ar.objs[i].obj.type == ObjType.Word)
                    {
                        var word = ar.objs[i].obj as Word;
                        var value = new Variable(word.name, this.objs[i % this.objs.Count].obj);
                        local.declare(word.name, value);
                        values.Add(new Item(LetterType.ClassObj) { obj = value });
                    }
                    else throw new Exception();
                }
                return new Array() { objs = values };

            }
            else if (val2.type == ObjType.Word)
            {

                var word = val2 as Word;
                var value = new Variable(word.name, this);
                local.declare(word.name, value);
                return value;
            }
            else throw new Exception();
        }
        public override Obj ResultReason(Obj val2, Local local, Line line)
        {
            return this.Setter(val2, local, line, ExeType.Reason);
        }
        public override Obj Self(Local local, Line line, ExeType type)
        {
            var ar = Clone as Array;
            for (var i = 0; i < ar.opess.Count; i++)
            {
                Item item = null;
                var opes = ar.opess[i];
                for (var j = 0; j < opes.Length; j++)
                {
                    if (opes[j] == null) continue;
                    for (var k = 0; k < opes[j].Count; k++)
                    {
                        if (j == 0) opes[k][k].obj.Self(local, line, type);
                        else item = ar.objs[i] = opes[j][k].Ope(local, line, type);
                    }
                }
                if (item == null)
                {
                    ar.objs[i].Self(local, line, type);
                    if (type == ExeType.Feel || type == ExeType.Reason) ar.objs[i].obj = ar.objs[i].obj.Getter(local, line, type);
                }
                ar.objs[i].obj = ar.objs[i].Self(local, line, type);
            }
            return ar;
        }
        public override Obj Clone
        {
            get
            {
                var ar = new Array();
                for (var i = 0; i < objs.Count; i++)
                {
                    var start = objs[i];
                    for (var j = start; ; j = j.next)
                    {
                        ar.add(j.Clone);
                        if (j.next == start) break;
                    }
                    ar.next();
                }
                ar.labelmap = labelmap;
                return ar;
            }
        }
        public override Obj Draw(Array ar, Local local, Line line, ExeType type)
        {
            if (ar.objs[0].obj.type == ObjType.Number || ar.objs[0].obj.type == ObjType.StrObj)
            {
                return new ArrayVal(this, ar.objs[0].obj);
            }
            throw new Exception();
        }
    }
    partial class ArrayVal : Obj
    {
        public Array ar;
        public Obj key;
        public ArrayVal(Array ar, Obj key) : base(ObjType.ArrayVal)
        {
            this.ar = ar; this.key = key;
        }
        public override Obj Getter(Local local, Line line, ExeType type)
        {
            if (key.type == ObjType.StrObj)
            {
                var str = key as StrObj;
                return ar.objs[ar.labelmap[str.str].n].obj;
            }
            else if (key.type == ObjType.Number)
            {
                var num = key as Number;
                return ar.objs[num.num].obj;
            }
            throw new Exception();
        }
        public override Obj Setter(Obj obj, Local local, Line line, ExeType type)
        {
        head:
            if (obj.type == ObjType.Block)
            {
                obj.type = ObjType.Array;
            }
            if (key.type == ObjType.StrObj)
            {
                var str = key as StrObj;
                if (!ar.labelmap.ContainsKey(str.str))
                {
                    ar.objs.Add(new Item(LetterType.Value) { obj = obj });
                }
                ar.objs[ar.labelmap[str.str].n].obj = obj;
                return obj;
            }
            else if (key.type == ObjType.Number)
            {
                var num = key as Number;
                ar.objs[num.num].obj = obj;
                return obj;
            }
            throw new Exception();
        }
        public override Obj Clone
        {
            get { return this; }
        }
        public override Obj ResultReason(Obj val2, Local local, Line line)
        {
            return Setter(val2, local, line, ExeType.Result);
        }
    }
    partial class Call : Obj
    {
        public Call() : base(ObjType.Call)
        {
            declare = new Block();
            block = new Block();
        }
        public Block declare;
        public Block block;
    }
    partial class Func : Value
    {
        public List<Dictionary<String, Obj>> values = new List<Dictionary<string, Obj>>();
        public Block block;
        public Call call;
        public bool copy;
        public Func(Obj clsobj, Call call) : base(clsobj, ObjType.Function)
        {
            this.call = call;
        }
        public void Block(List<Dictionary<String, Obj>> values)
        {
            this.values = new List<Dictionary<string, Obj>>();
            for (var i = 0; i < values.Count; i++)
            {
                this.values.Add(values[i]);
            }
        }
        public override Obj Draw(Array ar, Local local, Line line, ExeType type)
        {
            Func func = this;
            if (!copy)
            {
                func = new Func(clsobj, call);
                func.copy = true;
                func.block = block;
                func.Block(values);
                func.values.Add(new Dictionary<string, Obj>());
                foreach (var i in values[values.Count - 1].Keys)
                {
                    func.values[values.Count - 1][i] = values[values.Count - 1][i].Clone;
                }
            }
            return local.funcblock(func, ar, block);
        }
    }
    partial class Print : Func
    {
        public String name = "";
        public Print() : base(new Void(), null)
        {
        }
        public override Obj Draw(Array ar, Local local, Line line, ExeType type)
        {
            for (var i = 0; i < ar.objs.Count; i++)
            {
                var obj = ar.objs[i].obj;
            head:
                switch (obj.type)
                {
                    case ObjType.Word:
                        var word = obj as Word;
                        obj = local.get(word.name);
                        goto head;
                    case ObjType.Variable:
                        var variable = obj as Variable;
                        obj = variable.value;
                        goto head;
                    case ObjType.Number:
                        local.console.Text += (obj as Number).num.ToString() + "\n";
                        break;
                    case ObjType.StrObj:
                        local.console.Text += (obj as StrObj).str + "\n";
                        break;
                    case ObjType.Block:
                    case ObjType.Array:
                        var ar2 = obj as Array;
                        this.Draw(ar2, local, line, type);
                        break;
                    default:
                        throw new Exception();

                }
            }
            return new VoiVal();
        }
    }
    partial class Void : ClassObj
    {

    }
    partial class Str : ClassObj
    {

    }
    partial class Integer : ClassObj
    {

    }
    partial class Constructor : Func
    {
        public Constructor(Obj clsobj) : base(clsobj, null)
        {
            block = (clsobj as ClassObj).block;
        }
        public override Obj Draw(Array ar, Local local, Line line, ExeType type)
        {
            Constructor func = this;
            if (!copy)
            {
                var clsobj2 = clsobj as ClassObj;
                func = new Constructor(clsobj2);
                func.copy = true;
                func.block = block;
                for (var i = 0; i < clsobj2.values.Count - 1; i++)
                {
                    func.values.Add(clsobj2.values[i]);
                }
                func.values.Add(new Dictionary<string, Obj>());
                foreach (var i in clsobj2.values[clsobj2.values.Count - 1].Keys)
                {
                    func.values[clsobj2.values.Count - 1][i] = clsobj2.values[clsobj2.values.Count - 1][i].Clone;
                }
            }
            var clsobj3 = clsobj as ClassObj;
            var value = new Value(clsobj);
            if (clsobj3.extend != null)
            {
                value.vmap["base"] = new Base(clsobj3.extend, value);
            }
            return local.classblock(value, func, ar, block);
        }
    }
    partial class Base : Constructor
    {
        public Value value;
        public Base(Obj clsobj, Value value) : base(clsobj)
        {
            this.value = value;
        }
        public override Obj Draw(Array ar, Local local, Line line, ExeType type)
        {
            Base func = this;
            if (!copy)
            {
                var clsobj2 = clsobj as ClassObj;
                func = new Base(clsobj2, this.value);
                func.copy = true;
                func.block = block;
                for (var i = 0; i < clsobj2.values.Count - 1; i++)
                {
                    func.values.Add(clsobj2.values[i]);
                }
                func.values.Add(new Dictionary<string, Obj>());
                foreach (var i in clsobj2.values[clsobj2.values.Count - 1].Keys)
                {
                    func.values[clsobj2.values.Count - 1][i] = clsobj2.values[clsobj2.values.Count - 1][i].Clone;
                }
            }
            var clsobj3 = clsobj as ClassObj;
            if (clsobj3.extend != null)
            {
                value.vmap["base"] = new Base(clsobj3.extend, value);
            }
            else value.vmap["base"] = null;
            var oj = local.classblock(value, func, ar, block);
            value.vmap["base"] = this;
            return oj;
        }
    }
    partial class Property : Obj
    {
        public List<Dictionary<string, Obj>> values;
        public Obj clsobj;
        public Block block;
        public String name;
        public Property(Obj clsobj, Block block, String name = null) : base(ObjType.Property)
        {
            this.clsobj = clsobj;
            this.block = block;
            this.name = name;
         }
        public void Block(List<Dictionary<String, Obj>> values)
        {
            this.values = new List<Dictionary<string, Obj>>();
            for (var i = 0; i < values.Count; i++)
            {
                this.values.Add(values[i]);
            }
        }
        public override Obj Getter(Local local, Line line, ExeType type)
        {
            return local.propertyblock(this, null);
        }
        public override Obj Setter(Obj obj, Local local, Line line, ExeType type)
        {
            if (obj.type == ObjType.Block)
            {
                obj.type = ObjType.Array;
            }
            return local.propertyblock(this, obj);
        }
        public override Obj ResultReason(Obj val2, Local local, Line line)
        {
            return Setter(val2, local, line, ExeType.Result);
        }
        public override Obj Clone
        {
            get { return this; }
        }
    }
    partial class Type : Obj
    {
        public Accesor accesor = Accesor.Private;
        public Obj clsobj;
        public Obj chobj;
        public int array = 0;
        public Type(Obj clsobj) : base(ObjType.Type)
        {
            this.clsobj = clsobj;
        }
        public List<Obj> draws = new List<Obj>();
        public override Obj FeelResult(Obj val2, Local local, Line line)
        {
            if (val2.type == ObjType.Block)
            {
                var ar = val2 as Array;
                var rets = new List<Item>();
                for (var i = 0; i < ar.objs.Count; i++)
                {
                    if (ar.objs[i].obj.type == ObjType.Word)
                    {
                        var word = ar.objs[i].obj as Word;
                        if (word.call == null)
                        {
                            if (line.block == null)
                            {
                                var value = new Variable(word.name, this);
                                local.declare(word.name, value);
                                rets.Add(new Item(LetterType.Value) { obj = value });
                            }
                            else
                            {
                                var property = new Property(this, line.block);
                                property.Block(local.values);
                                local.declare(word.name, property);
                                rets.Add(new Item(LetterType.Value) { obj = property });
                            }
                        }
                        else
                        {
                            var type = new Type(this);
                            var func = new Func(this, word.call);
                            func.Block(local.values);
                            local.declarefunc2(func, func.call);
                            var variable = new Variable(word.name, this) { value = func };
                            local.declare(word.name, variable);
                            var varray = new List<Obj>(func.values[func.values.Count - 1].Values);
                            for (var j = 0; j < varray.Count; j++) type.draws.Add((varray[j] as Variable).clsobj);
                            rets.Add(new Item(LetterType.Func) { obj = variable });
                        }
                    }
                    else throw new Exception();
                }
                return new Array() { objs = rets };

            }
            else if (val2.type == ObjType.Word)
            {

                var word = val2 as Word;
                if (word.call == null)
                {
                    if (line.block == null)
                    {
                        var value = new Variable(word.name, this);
                        local.declare(word.name, value);
                        return value;
                    }
                    else
                    {
                        var property = new Property(this, line.block);
                        property.Block(local.values);
                        local.declare(word.name, property);
                        return property;
                    }
                }
                else
                {
                    var func = new Func(this, word.call);
                    func.Block(local.values);
                    local.declarefunc2(func, func.call);
                    var variable = new Variable(word.name, this) { value = func };
                    local.declare(word.name, variable);
                    return variable;
                }
            }
            else throw new Exception();
        }
        public override Obj Left(Item val2, Local local, Line line, ExeType type)
        {
            var kata = new Type(this);
            if (val2.obj.type == ObjType.Word)
            {
                var obj = val2.obj.Self(local, line, type);
                if (obj.type == ObjType.ClassObj || obj.type == ObjType.Var)
                {
                    kata.draws.Add(obj);
                    return kata;
                }
                else throw new Exception();

            }
            else if (val2.obj.type == ObjType.Block)
            {
                var ar = val2.obj as Array;
                for (var i = 0; i < ar.objs.Count; i++)
                {
                    var obj = ar.objs[i].obj;
                    if (obj.type == ObjType.ClassObj || obj.type == ObjType.Var)
                    {
                        kata.draws.Add(obj);
                    }
                    else throw new Exception();
                }
                return kata;
            }
            throw new Exception();
        }
        public override Obj Draw(Array ar, Local local, Line line, ExeType type)
        {
            if (ar.objs.Count == 0)
            {
                var typeobj = new Type(this) { draws = draws , name = name};
                typeobj.array = this.array + 1;
                return typeobj;
            }
            throw new Exception();
        }
        public override Obj Call(Call call, Local local, Line line, ExeType type)
        {
            var func = new Func(this, call);
            func.Block(local.values);
            local.declarefunc2(func, func.call);
            return func;
        }
        public override Obj Clone
        {
            get { return new Type(clsobj) { draws = draws, accesor = accesor, array = array }; }
        }
    }
    partial class ClassObj : Obj
    {
        public List<Dictionary<String, Obj>> values = new List<Dictionary<string, Obj>>();
        public Block block;
        public ClassObj extend;
        public ClassObj() : base(ObjType.ClassObj)
        {
        }
        public void Block(List<Dictionary<String, Obj>> values)
        {
            this.values = new List<Dictionary<string, Obj>>();
            for (var i = 0; i < values.Count; i++)
            {
                this.values.Add(values[i]);
            }
        }
        public void Extend(Obj obj)
        {
        head:
            if (obj == null) return;
            else if (obj.type == ObjType.ClassObj)
            {
                extend = obj as ClassObj;
            }
            else if (obj.type == ObjType.Variable)
            {
                obj = (obj as Variable).value;
                goto head;
            }
            else throw new Exception();
        }
        public override Obj Dot(Obj val2, Local local, Line line, ExeType type)
        {
            if (val2.type == ObjType.Word)
            {
                var word = val2 as Word;
                if (word.name == "new") return new Constructor(this);
            }
            return null;
        }
        public override Obj Left(Item val2, Local local, Line line, ExeType type)
        {
            var kata = new Type(this as ClassObj);
            if (val2.obj.type == ObjType.Word)
            {
                var obj = val2.obj.Self(local, line, type);
                if (obj.type == ObjType.ClassObj || obj.type == ObjType.Var)
                {
                    kata.draws.Add(obj);
                    return kata;
                }
                else throw new Exception();

            }
            else if (val2.obj.type == ObjType.Block)
            {
                var ar = val2.obj as Array;
                for (var i = 0; i < ar.objs.Count; i++)
                {
                    var obj = ar.objs[i].obj;
                    if (obj.type == ObjType.ClassObj || obj.type == ObjType.Var)
                    {
                        kata.draws.Add(obj);
                    }
                    else throw new Exception();
                }
                return kata;
            }
            throw new Exception();
        }
        public override Obj FeelResult(Obj val2, Local local, Line line)
        {
            if (val2.type == ObjType.Block)
            {
                var ar = val2 as Array;
                var rets = new List<Item>();
                for (var i = 0; i < ar.objs.Count; i++)
                {
                    if (ar.objs[i].obj.type == ObjType.Word)
                    {
                        var word = ar.objs[i].obj as Word;
                        if (word.call == null)
                        {
                            if (line.block == null)
                            {
                                var value = new Variable(word.name, this);
                                local.declare(word.name, value);
                                rets.Add(new Item(LetterType.Value) { obj = value });
                            }
                            else
                            {
                                var property = new Property(this, line.block);
                                property.Block(local.values);
                                local.declare(word.name, property);
                                rets.Add(new Item(LetterType.Value) { obj = property });
                            }
                        }
                        else
                        {
                            var type = new Type(this);
                            var func = new Func(this, word.call);
                            func.Block(local.values);
                            local.declarefunc2(func, func.call);
                            var variable = new Variable(word.name, this) { value = func };
                            local.declare(word.name, variable);
                            var varray = new List<Obj>(func.values[func.values.Count - 1].Values);
                            for (var j = 0; j < varray.Count; j++) type.draws.Add((varray[j] as Variable).clsobj);
                            rets.Add(new Item(LetterType.Func) { obj = variable });
                        }
                    }
                    else throw new Exception();
                }
                return new Array() { objs = rets };

            }
            else if (val2.type == ObjType.Word)
            {

                var word = val2 as Word;
                if (word.call == null)
                {
                    if (line.block == null)
                    {
                        var value = new Variable(word.name, this);
                        local.declare(word.name, value);
                        return value;
                    }
                    else
                    {
                        var property = new Property(this, line.block);
                        property.Block(local.values);
                        local.declare(word.name, property);
                        return property;
                    }
                }
                else
                {
                    var func = new Func(this, word.call);
                    func.Block(local.values);
                    local.declarefunc2(func, func.call);
                    var variable = new Variable(word.name, this) { value = func };
                    local.declare(word.name, variable);
                    return variable;
                }
            }
            else throw new Exception();
        }
        public override Obj Draw(Array ar, Local local, Line line, ExeType type)
        {
            if (ar.objs.Count == 0)
            {
                var typeobj = new Type(this);
                typeobj.array++;
                return typeobj;
            }
            throw new Exception();
        }
        public override Obj Call(Call call, Local local, Line line, ExeType type)
        {
            var func = new Func(this, call);
            func.Block(local.values);
            local.declarefunc2(func, func.call);
            return func;
        }
    }
    partial class StrObj : Value
    {
        public String str;
        public StrObj(String str, Obj clsobj) : base(clsobj, ObjType.StrObj)
        {
            this.str = str;
            this.clsobj = clsobj;
        }
        public override Obj Clone
        {
            get { return new StrObj(str, clsobj as ClassObj); }
        }
        public override Obj Plus(Obj val2, Local local, Line line, ExeType type)
        {
            var obj2 = val2;
        head:
            if (obj2.type == ObjType.Number)
            {
                var number = (obj2 as Number);
                return new StrObj(str + number.num, clsobj as ClassObj);
            }
            else if (obj2.type == ObjType.StrObj)
            {
                var strobj = (obj2 as StrObj);
                return new StrObj(str + strobj.str, clsobj as ClassObj);
            }
            else if (val2.type == ObjType.Word)
            {
                var word = obj2 as Word;
                obj2 = local.get(word.name);
                goto head;
            }
            else if (obj2.type == ObjType.Variable)
            {
                var variable = obj2 as Variable;
                obj2 = variable.value;
                goto head;
            }
            else if (obj2.type == ObjType.Block)
            {
                var ar = obj2 as Array;
                if (ar.objs.Count == 1)
                {
                    obj2 = ar.objs[0].obj;
                    goto head;
                }
            }
            throw new Exception();
        }
        public override Obj Minus(Obj val2, Local local, Line line, ExeType type)
        {
            throw new Exception();
        }
        public override Obj EqualEqual(Obj val2, Local local, Line line, ExeType type)
        {
            var obj2 = val2;
        head:
            if (obj2.type == ObjType.StrObj)
            {
                var strobj = (obj2 as StrObj);
                return new BoolVal(str == strobj.str, local.get("bool"));
            }
            else if (val2.type == ObjType.Word)
            {
                var word = obj2 as Word;
                obj2 = local.get(word.name);
                goto head;
            }
            else if (obj2.type == ObjType.Variable)
            {
                var variable = obj2 as Variable;
                obj2 = variable.value;
                goto head;
            }
            else if (obj2.type == ObjType.Block)
            {
                var ar = obj2 as Array;
                if (ar.objs.Count == 1)
                {
                    obj2 = ar.objs[0].obj;
                    goto head;
                }
            }
            throw new Exception();
        }

    }
    partial class Null : Value
    {
        public Null() : base(null, ObjType.Null) { }
    }
    partial class Bool : ClassObj
    {
        public Bool() : base() { }
    }
    partial class BoolVal : Value
    {
        public bool val;
        public BoolVal(bool val, Obj clsobj) : base(clsobj, ObjType.BoolVal)
        {
            this.val = val;
        }
        public override Obj Clone
        {
            get { return new BoolVal(val, clsobj as ClassObj); }
        }
    }
    partial class Number : Value
    {
        public int num;
        public Number(int num, Obj clsobj) : base(clsobj, ObjType.Number)
        {
            this.num = num;
            this.clsobj = clsobj;
        }
        public override Obj Clone
        {
            get { return new Number(num, clsobj); }
        }
        public override Obj Plus(Obj val2, Local local, Line line, ExeType type)
        {
            var obj2 = val2;
        head:
            if (obj2.type == ObjType.Number)
            {
                var number = (obj2 as Number);
                return new Number(num + number.num, clsobj as ClassObj);
            }
            else if (obj2.type == ObjType.StrObj)
            {
                var strobj = (obj2 as StrObj);
                return new StrObj(num + strobj.str, strobj.clsobj as ClassObj);
            }
            else if (val2.type == ObjType.Word)
            {
                var word = obj2 as Word;
                obj2 = local.get(word.name);
                goto head;
            }
            else if (obj2.type == ObjType.Variable)
            {
                var variable = obj2 as Variable;
                obj2 = variable.value;
                goto head;
            }
            else if (obj2.type == ObjType.Block)
            {
                var ar = obj2 as Array;
                if (ar.objs.Count == 1)
                {
                    obj2 = ar.objs[0].obj;
                    goto head;
                }
            }
            throw new Exception();
        }
        public override Obj Minus(Obj val2, Local local, Line line, ExeType type)
        {
            var obj2 = val2;
        head:
            if (obj2.type == ObjType.Number)
            {
                var number = (obj2 as Number);
                return new Number(num - number.num, clsobj as ClassObj);
            }
            else if (val2.type == ObjType.Word)
            {
                var word = obj2 as Word;
                obj2 = local.get(word.name);
                goto head;
            }
            else if (obj2.type == ObjType.Variable)
            {
                var variable = obj2 as Variable;
                obj2 = variable.value;
                goto head;
            }
            else if (obj2.type == ObjType.Block)
            {
                var ar = obj2 as Array;
                if (ar.objs.Count == 1)
                {
                    obj2 = ar.objs[0].obj;
                    goto head;
                }
            }
            throw new Exception();
        }
        public override Obj Mul(Obj val2, Local local, Line line, ExeType type)
        {
            var obj2 = val2;
        head:
            if (obj2.type == ObjType.Number)
            {
                var number = (obj2 as Number);
                return new Number(num * number.num, clsobj as ClassObj);
            }
            else if (obj2.type == ObjType.Variable)
            {
                var variable = obj2 as Variable;
                obj2 = variable.value;
                goto head;
            }
            else if (obj2.type == ObjType.Block)
            {
                var ar = obj2 as Array;
                if (ar.objs.Count == 1)
                {
                    obj2 = ar.objs[0].obj;
                    goto head;
                }
            }
            throw new Exception();
        }
        public override Obj Div(Obj val2, Local local, Line line, ExeType type)
        {
            var obj2 = val2;
        head:
            if (obj2.type == ObjType.Number)
            {
                var number = (obj2 as Number);
                return new Number(num / number.num, clsobj as ClassObj);
            }
            else if (val2.type == ObjType.Word)
            {
                var word = obj2 as Word;
                obj2 = local.get(word.name);
                goto head;
            }
            else if (obj2.type == ObjType.Variable)
            {
                var variable = obj2 as Variable;
                obj2 = variable.value;
                goto head;
            }
            else if (obj2.type == ObjType.Block)
            {
                var ar = obj2 as Array;
                if (ar.objs.Count == 1)
                {
                    obj2 = ar.objs[0].obj;
                    goto head;
                }
            }
            throw new Exception();
        }
        public override Obj EqualEqual(Obj val2, Local local, Line line, ExeType type)
        {
            var obj2 = val2;
        head:
            if (obj2.type == ObjType.Number)
            {
                var number = (obj2 as Number);
                return new BoolVal(num == number.num, local.get("bool"));
            }
            else if (val2.type == ObjType.Word)
            {
                var word = obj2 as Word;
                obj2 = local.get(word.name);
                goto head;
            }
            else if (obj2.type == ObjType.Variable)
            {
                var variable = obj2 as Variable;
                obj2 = variable.value;
                goto head;
            }
            else if (obj2.type == ObjType.Block)
            {
                var ar = obj2 as Array;
                if (ar.objs.Count == 1)
                {
                    obj2 = ar.objs[0].obj;
                    goto head;
                }
            }
            throw new Exception();
        }
        public override Obj LessThan(Obj val2, Local local, Line line, ExeType type)
        {
            var obj2 = val2;
        head:
            if (obj2.type == ObjType.Number)
            {
                var number = (obj2 as Number);
                return new BoolVal(num < number.num, local.get("bool"));
            }
            else if (val2.type == ObjType.Word)
            {
                var word = obj2 as Word;
                obj2 = local.get(word.name);
                goto head;
            }
            else if (obj2.type == ObjType.Variable)
            {
                var variable = obj2 as Variable;
                obj2 = variable.value;
                goto head;
            }
            throw new Exception();
        }
        public override Obj MoreThan(Obj val2, Local local, Line line, ExeType type)
        {
            var obj2 = val2;
        head:
            if (obj2.type == ObjType.Number)
            {
                var number = (obj2 as Number);
                return new BoolVal(num > number.num, local.get("bool"));
            }
            else if (val2.type == ObjType.Word)
            {
                var word = obj2 as Word;
                obj2 = local.get(word.name);
                goto head;
            }
            else if (obj2.type == ObjType.Variable)
            {
                var variable = obj2 as Variable;
                obj2 = variable.value;
                goto head;
            }
            else if (obj2.type == ObjType.Block)
            {
                var ar = obj2 as Array;
                if (ar.objs.Count == 1)
                {
                    obj2 = ar.objs[0].obj;
                    goto head;
                }
            }
            throw new Exception();
        }
        public override Obj LessEqual(Obj val2, Local local, Line line, ExeType type)
        {
            var obj2 = val2;
        head:
            if (obj2.type == ObjType.Number)
            {
                var number = (obj2 as Number);
                return new BoolVal(num <= number.num, local.get("bool"));
            }
            else if (val2.type == ObjType.Word)
            {
                var word = obj2 as Word;
                obj2 = local.get(word.name);
                goto head;
            }
            else if (obj2.type == ObjType.Variable)
            {
                var variable = obj2 as Variable;
                obj2 = variable.value;
                goto head;
            }
            else if (obj2.type == ObjType.Block)
            {
                var ar = obj2 as Array;
                if (ar.objs.Count == 1)
                {
                    obj2 = ar.objs[0].obj;
                    goto head;
                }
            }
            throw new Exception();
        }
        public override Obj MoreEqual(Obj val2, Local local, Line line, ExeType type)
        {
            var obj2 = val2;
        head:
            if (obj2.type == ObjType.Number)
            {
                var number = (obj2 as Number);
                return new BoolVal(num >= number.num, local.get("bool"));
            }
            else if (val2.type == ObjType.Word)
            {
                var word = obj2 as Word;
                obj2 = local.get(word.name);
                goto head;
            }
            else if (obj2.type == ObjType.Variable)
            {
                var variable = obj2 as Variable;
                obj2 = variable.value;
                goto head;
            }
            else if (obj2.type == ObjType.Block)
            {
                var ar = obj2 as Array;
                if (ar.objs.Count == 1)
                {
                    obj2 = ar.objs[0].obj;
                    goto head;
                }
            }
            throw new Exception();
        }
    }
    partial class VoiVal : Value
    {
        public VoiVal() : base(null, ObjType.VoiVal)
        {

        }
    }
    partial class Variable : Obj
    {
        public String name;
        public Accesor accesor = Accesor.Private;
        public Obj clsobj;
        public Obj value;
        public override Obj Clone
        {
            get { return new Variable(name, clsobj) { accesor = accesor, value = value }; }
        }
        public Variable(String name, Obj clsobj) : base(ObjType.Variable)
        {
            this.name = name;
            this.clsobj = clsobj;
        }
        public override Obj Setter(Obj obj, Local local, Line line, ExeType type)
        {
            if (obj.type == ObjType.Block)
            {
                obj.type = ObjType.Array;
            }
            else if (obj.type == ObjType.Variable)
            {
                obj = (obj as Variable).value;
            }
            var obj2 = TypeCheck.Check(clsobj, obj, CheckType.Setter);
            value = obj;
            return this;
        }
        public override Obj Plus(Obj val2, Local local, Line line, ExeType type)
        {
            return value.Plus(val2, local, line, type);
        }
        public override Obj Draw(Array ar, Local local, Line line, ExeType type)
        {
            if (value.type == ObjType.Function)
            {
                return value.Draw(ar, local, line, type);
            }
            else if (value.type == ObjType.Array)
            {
                return value.Draw(ar, local, line, type);
            }
            throw new Exception();
        }
        public override Obj Minus(Obj val2, Local local, Line line, ExeType type)
        {
            return value.Minus(val2, local, line, type);
        }
        public override Obj Mul(Obj val2, Local local, Line line, ExeType type)
        {
            return value.Mul(val2, local, line, type);
        }
        public override Obj Div(Obj val2, Local local, Line line, ExeType type)
        {
            return value.Div(val2, local, line, type);
        }
        public override Obj EqualEqual(Obj val2, Local local, Line line, ExeType type)
        {
            return value.EqualEqual(val2, local, line, type);
        }
        public override Obj LessThan(Obj val2, Local local, Line line, ExeType type)
        {
            return value.LessThan(val2, local, line, type);
        }
        public override Obj MoreThan(Obj val2, Local local, Line line, ExeType type)
        {
            return value.MoreThan(val2, local, line, type);
        }
        public override Obj LessEqual(Obj val2, Local local, Line line, ExeType type)
        {
            return value.LessEqual(val2, local, line, type);
        }
        public override Obj MoreEqual(Obj val2, Local local, Line line, ExeType type)
        {
            return value.MoreEqual(val2, local, line, type);
        }
        public override Obj Dot(Obj val2, Local local, Line line, ExeType type)
        {
            return value.Dot(val2, local, line, type);
        }
        /*public override Obj Call(Call call, Local local, Line line, ExeType type)
        {
            var values = local.callcheck(call);
            if (clsobj.type == ObjType.Type)
            {
                var co = clsobj as Type;
                if (co.draws.Count < values.Count) throw new Exception();
                var i = 0;
                foreach (var v in values.Values)
                {
                    if (v.type == ObjType.Var) { }
                    else if (v.type == ObjType.ClassObj)
                    {
                        if (co.draws[i].type == ObjType.Var)
                        {
                            co.draws[i] = v;
                        }
                        else if (co.draws[i].type == ObjType.ClassObj)
                        {
                            if (co.draws[i] != v) throw new Exception();
                        }
                        else throw new Exception();
                    }
                    i++;
                }
                var func = new Func(co.clsobj, call);
                func.block = call.block;
                func.Block(local.values);
                func.values.Add(new Dictionary<string, Obj>());
                func.values.Add(values);
                value = func;
                return func;
            }
            throw new Exception();
        }*/
        public override Obj ResultReason(Obj val2, Local local, Line line)
        {
        head:
            if (val2.type == ObjType.Value)
            {
                if (clsobj.type == ObjType.Var)
                {
                    clsobj = (val2 as Value).clsobj;
                    return Setter(val2, local, line, ExeType.Result);
                }
                else if (clsobj.type == ObjType.ClassObj)
                {
                    if (clsobj == (val2 as Value).clsobj)
                    {
                        return Setter(val2, local, line, ExeType.Result);
                    }
                }
                else if (clsobj.type == ObjType.Type)
                {
                    var typeobj = clsobj as Type;
                    if (typeobj.clsobj == clsobj && typeobj.array == 0) return Setter(val2, local, line, ExeType.Result);
                }
            }
            else if (val2.type == ObjType.Variable)
            {
                var variable = val2 as Variable;
                val2 = variable.value;
                goto head;
            }
            else if (val2.type == ObjType.ClassObj)
            {
                var clsobj = val2 as ClassObj;
                value = clsobj;
                return this;
            }
            else if (val2.type == ObjType.Function)
            {
                var func = val2 as Func;
                return Setter(func, local, line, ExeType.Result);
            }
            else if (val2.type == ObjType.Number)
            {
                if (clsobj.type == ObjType.Var)
                {
                    clsobj = (val2 as Value).clsobj;
                    return Setter(val2, local, line, ExeType.Result);
                }
                else if (clsobj.type == ObjType.ClassObj)
                {
                    if (clsobj == (val2 as Value).clsobj)
                    {
                        return Setter(val2, local, line, ExeType.Result);
                    }
                }
                else if (clsobj.type == ObjType.Type)
                {
                    var typeobj = clsobj as Type;
                    if (typeobj.clsobj == clsobj && typeobj.array == 0) return Setter(val2, local, line, ExeType.Result);
                }
            }
            else if (val2.type == ObjType.Block)
            {
                return Setter(val2, local, line, ExeType.Result);
            }
            throw new Exception();
        }
    }
    partial class Value : Obj
    {
        public Obj clsobj;
        public Dictionary<String, Obj> vmap = new Dictionary<string, Obj>();
        public Value(Obj clsobj) : base(ObjType.Value)
        {
            this.clsobj = clsobj;
        }
        public Value(Constructor cons) : base(ObjType.Value)
        {
            this.clsobj = cons.clsobj;
        }
        public Value(Obj clsobj, ObjType type) : base(type)
        {
            this.clsobj = clsobj;
        }
        public override Obj Dot(Obj val2, Local local, Line line, ExeType type)
        {
            if (val2.type == ObjType.Word)
            {
                var word = val2 as Word;
                if (vmap.ContainsKey(word.name)) return vmap[word.name];
            }
            return null;
        }
    }
    partial class If : Obj
    {
        public Block block;
        public If() : base(ObjType.If) { }
        public override Obj FeelResult(Obj val2, Local local, Line line)
        {
            var obj2 = val2;
        head:
            if (obj2.type == ObjType.Number)
            {
                var number = (obj2 as Number);
                if (number.num != 0) return this;
                else return null;
            }
            else if (obj2.type == ObjType.StrObj)
            {
                var str = obj2 as StrObj;
                if (str.str.Length != 0) return this;
                else return null;

            }
            else if (obj2.type == ObjType.BoolVal)
            {
                var boolobj = obj2 as BoolVal;
                if (boolobj.val) return this;
                else return null;
            }
            else if (val2.type == ObjType.Word)
            {
                var word = obj2 as Word;
                obj2 = local.get(word.name);
                goto head;
            }
            else if (obj2.type == ObjType.Variable)
            {
                var variable = obj2 as Variable;
                obj2 = variable.value;
                goto head;
            }
            else if (obj2.type == ObjType.Block)
            {
                var ar = obj2 as Array;
                if (ar.objs.Count == 1)
                {
                    obj2 = ar.objs[0].obj;
                    goto head;
                }
            }
            throw new Exception();
        }
        public override Obj ResultReason(Obj val2, Local local, Line line)
        {
            return val2;
        }
        public override Obj Clone
        {
            get { return this; }
        }
    }
    partial class Elif : Obj
    {
        public Block block;
        public Elif() : base(ObjType.Elif) { }
        public override Obj FeelResult(Obj val2, Local local, Line line)
        {
            var obj2 = val2;
        head:
            if (obj2.type == ObjType.Number)
            {
                var number = (obj2 as Number);
                if (number.num != 0) return this;
                else return null;
            }
            else if (obj2.type == ObjType.StrObj)
            {
                var str = obj2 as StrObj;
                if (str.str.Length != 0) return this;
                else return null;

            }
            else if (obj2.type == ObjType.BoolVal)
            {
                var boolobj = obj2 as BoolVal;
                if (boolobj.val) return this;
                else return null;
            }
            else if (obj2.type == ObjType.Word)
            {
                var word = obj2 as Word;
                obj2 = local.get(word.name);
                goto head;
            }
            else if (obj2.type == ObjType.Variable)
            {
                var variable = obj2 as Variable;
                obj2 = variable.value;
                goto head;
            }
            else if (obj2.type == ObjType.Block)
            {
                var ar = obj2 as Array;
                if (ar.objs.Count == 1)
                {
                    obj2 = ar.objs[0].obj;
                    goto head;
                }
            }
            throw new Exception();
        }
        public override Obj ResultReason(Obj val2, Local local, Line line)
        {
            return val2;
        }
        public override Obj Clone
        {
            get { return this; }
        }
    }
    partial class Else : Obj
    {
        public Block block;
        public Else() : base(ObjType.Else) { }
        public override Obj ResultReason(Obj val2, Local local, Line line)
        {
            return this;
        }
        public override Obj Clone
        {
            get { return this; }
        }
    }
    partial class Return : Obj
    {
        public Obj value;
        public Return() : base(ObjType.Return) { }
        public override Obj Clone
        {
            get { return this; }
        }
        public override Obj Draw(Array ar, Local local, Line line, ExeType type)
        {
            var obj = ar.objs[0].obj;
        head:
            if (obj.type == ObjType.Variable)
            {
                obj = (obj as Variable).value;
                goto head;
            }
            else if (obj.type == ObjType.Number || obj.type == ObjType.StrObj || obj.type == ObjType.Value || obj.type == ObjType.Array || obj.type == ObjType.Block)
            {
                value = obj;
                return this;
            }
            else if (obj.type == ObjType.Block)
            {
                var ar2 = obj as Array;
                if (ar2.objs.Count == 1)
                {
                    obj = ar2.objs[0].obj;
                    goto head;
                }
            }
            throw new Exception();
        }
    }
    partial class Goto : Obj
    {
        public String value;
        public Goto() : base(ObjType.Goto)
        {

        }
        public override Obj Draw(Array ar, Local local, Line line, ExeType type)
        {
            var obj = ar.objs[0].obj;
            if (obj.type == ObjType.Number)
            {
                value = (obj as Number).num.ToString();
                return this;
            }
            else if (obj.type == ObjType.StrObj)
            {
                value = (obj as StrObj).str;
                return this;
            }
            else if (obj.type == ObjType.BoolVal)
            {
                value = (obj as BoolVal).val == true ? "true" : "false";
                return this;
            }
            throw new Exception();
        }
        public override Obj Clone
        {
            get { return this; }
        }
    }
    partial class While : Obj
    {
        public While() : base(ObjType.While)
        {
        }
        public override Obj FeelResult(Obj val2, Local local, Line line)
        {
            var obj2 = val2;
        head:
            if (obj2.type == ObjType.Number)
            {
                var number = (obj2 as Number);
                if (number.num != 0) return this;
                else return null;
            }
            else if (obj2.type == ObjType.Word)
            {
                var word = obj2 as Word;
                obj2 = local.get(word.name);
                goto head;
            }
            else if (obj2.type == ObjType.StrObj)
            {
                var str = obj2 as StrObj;
                if (str.str.Length != 0) return this;
                else return null;

            }
            else if (obj2.type == ObjType.BoolVal)
            {
                var boolobj = obj2 as BoolVal;
                if (boolobj.val) return this;
                else return null;
            }
            else if (obj2.type == ObjType.Variable)
            {
                var variable = obj2 as Variable;
                obj2 = variable.value;
                goto head;
            }
            else if (obj2.type == ObjType.Block)
            {
                var ar = obj2 as Array;
                if (ar.objs.Count == 1)
                {
                    obj2 = ar.objs[0].obj;
                    goto head;
                }
            }
            throw new Exception();
        }
        public override Obj Clone
        {
            get { return this; }
        }
    }
    partial class For : Obj
    {
        public List<Variable> variables = new List<Variable>();
        public Obj extend;
        public Call call;
        public For() : base(ObjType.For)
        {

        }
        public override Obj FeelResult(Obj val2, Local local, Line line)
        {
            if (val2.type == ObjType.Block)
            {
                var ar = val2 as Array;
                var clsobjs = new List<Item>();
                for (var i = 0; i < ar.objs.Count; i++)
                {
                    if (ar.objs[i].obj.type == ObjType.Word)
                    {
                        var word = ar.objs[i].obj as Word;
                        var variable = new Variable(word.name,new Var());
                        variables.Add(variable);
                        local.declare(word.name, variable);
                    }
                    else throw new Exception();
                }
                return this;

            }
            else if (val2.type == ObjType.Word)
            {
                var word = val2 as Word;
                extend = word.extend;
                var variable = new Variable(word.name, new Var());
                variables.Add(variable);
                local.declare(word.name, variable);
                return this;
            }
            else throw new Exception();
        }
        public override Obj Call(Call call, Local local, Line line, ExeType type)
        {
            this.call = call;
            return this;
        }
        public override Obj Clone
        {
            get { return this; }
        }
    }
    partial class Break : Obj
    {
        public Break() : base(ObjType.Break)
        {

        }
        public override Obj Clone
        {
            get { return this; }
        }
    }
    partial class Continue : Obj
    {
        public Continue() : base(ObjType.Continue)
        {

        }
        public override Obj Clone
        {
            get { return this; }
        }
    }
    partial class Switch : Obj
    {
        public Obj clsobj;
        public String value;
        public Switch() : base(ObjType.Switch) { }
        public override Obj FeelResult(Obj val2, Local local, Line line)
        {
            var obj2 = val2;
        head:
            if (obj2.type == ObjType.Number)
            {
                var value = obj2 as Number;
                clsobj = value.clsobj;
                this.value = value.num.ToString();
                return this;
            }
            else if (obj2.type == ObjType.StrObj)
            {
                var value = obj2 as StrObj;
                clsobj = value.clsobj;
                this.value = value.str;
                return this;
            }
            else if (obj2.type == ObjType.BoolVal)
            {
                var value = obj2 as BoolVal;
                clsobj = value.clsobj;
                this.value = value.val == true ? "true" : "false";
                return this;
            }
            else if (obj2.type == ObjType.Word)
            {
                var word = obj2 as Word;
                obj2 = local.get(word.name);
                goto head;
            }
            else if (obj2.type == ObjType.Variable)
            {
                var variable = obj2 as Variable;
                obj2 = variable.value;
                goto head;
            }
            else if (obj2.type == ObjType.Block)
            {
                var ar = obj2 as Array;
                if (ar.objs.Count == 1)
                {
                    obj2 = ar.objs[0].obj;
                    goto head;
                }
            }
            throw new Exception();
        }
        public override Obj Clone
        {
            get { return this; }
        }

    }

この記事が気に入ったらサポートをしてみませんか?