예제 #1
0
        private void CompileBinOp(AstBinOp node, Syt syt, StringBuilder sb)
        {
            CompileRecursive(node.exprLeft, syt, sb);
            CompileRecursive(node.exprRight, syt, sb);

            switch (node.KBinop)
            {
            case KBinop.Plus: sb.AppendLine("add"); break;

            case KBinop.Minus: sb.AppendLine("sub"); break;

            case KBinop.And: sb.AppendLine("and"); break;

            case KBinop.Or: sb.AppendLine("or"); break;

            case KBinop.Lt: sb.AppendLine("lt"); break;

            case KBinop.Gt: sb.AppendLine("gt"); break;

            case KBinop.Eq: sb.AppendLine("eq"); break;

            case KBinop.Mul: sb.AppendLine("call Math.multiply 2"); break;

            case KBinop.Div: sb.AppendLine("call Math.divide 2"); break;

            default:
                throw new ArgumentOutOfRangeException();
            }
        }
예제 #2
0
        private void CompileLet(AstLet node, Syt syt, StringBuilder sb)
        {
            CompileRecursive(node.exprRight, syt, sb);

            if (node.exprLeft is AstIndex)
            {
                var astIndex = (AstIndex)node.exprLeft;
                CompileRecursive(astIndex.exprLeft, syt, sb);
                CompileRecursive(astIndex.exprRight, syt, sb);
                sb.AppendLine("add");
                sb.AppendLine("pop pointer 1");
                sb.AppendLine("pop that 0");
                return;
            }

            if (node.exprLeft is AstVarRef)
            {
                var nodeVarRef = (AstVarRef)node.exprLeft;
                var syte       = syt.Lookup(nodeVarRef.StName);
                if (syte.Ksyte.FIn(Ksyte.Field, Ksyte.Arg, Ksyte.Var, Ksyte.Static))
                {
                    sb.AppendLine("pop {0} {1}".StFormat(StSegment(syte.Ksyte), syte.Isyte));
                }
                return;
            }

            throw new Erparse(node, "not an lvalue");
        }
예제 #3
0
        private void CompileSubroutine(AstSubroutine node, Syt syt, StringBuilder sb)
        {
            var sytFunc = new Syt(syt);

            sb.AppendLine("function {0} {1}".StFormat(node.FQName(), node.RgVarDeclDecl.Length));

            if (node.Ksubroutine == Ksubroutine.Constructor)
            {
                var csize = node.NodeAncestor <AstClass>().RgclassDecl.Length;
                sb.AppendLine("push constant {0}".StFormat(csize));
                sb.AppendLine("call Memory.alloc 1");
                sb.AppendLine("pop pointer 0");
            }
            else if (node.Ksubroutine == Ksubroutine.MemberFunction)
            {
                sb.AppendLine("push argument 0");
                sb.AppendLine("pop pointer 0");
                sytFunc.Add(Ksyte.Arg, "this", node.NodeAncestor <AstClass>().StName);
            }

            CompileRecursive(node.RgParam, sytFunc, sb);
            CompileRecursive(node.RgVarDeclDecl, sytFunc, sb);

            CompileRecursive(node.Body, sytFunc, sb);

            if (node.Type.Ktype == Ktype.Void)
            {
                sb.AppendLine("push constant 0");
                sb.AppendLine("return");
            }
        }
예제 #4
0
 private void CompileRecursive(IEnumerable <AstNode> rgnode, Syt syt, StringBuilder sb)
 {
     foreach (var node in rgnode)
     {
         CompileRecursive(node, syt, sb);
     }
 }
예제 #5
0
 private void CompileIndex(AstIndex node, Syt syt, StringBuilder sb)
 {
     CompileRecursive(node.exprLeft, syt, sb);
     CompileRecursive(node.exprRight, syt, sb);
     sb.AppendLine("add");
     sb.AppendLine("pop pointer 1");
     sb.AppendLine("push that 0");
 }
예제 #6
0
 private void CompileIntLit(AstIntLit node, Syt syt, StringBuilder sb)
 {
     sb.AppendLine("push constant " + Math.Abs(node.i));
     if (node.i < 0)
     {
         sb.AppendLine("neg");
     }
 }
예제 #7
0
 private void CompileBoolLit(AstBoolLit node, Syt syt, StringBuilder sb)
 {
     if (node.f)
     {
         sb.AppendLine("push constant 1");
         sb.AppendLine("neg");
     }
     else
         sb.AppendLine("push constant 0");
 }
예제 #8
0
        public string Compile(string st)
        {
            var sb      = new StringBuilder();
            var astNode = new JackParser().Parse(st);

            var syt = new Syt(null);

            CompileRecursive(astNode, syt, sb);

            return(sb.ToString());
        }
예제 #9
0
        public string Compile(string st)
        {
            var sb = new StringBuilder();
            var astNode = new JackParser().Parse(st);

            var syt = new Syt(null);

            CompileRecursive(astNode, syt, sb);

            return sb.ToString();
        }
예제 #10
0
 private void CompileStringLit(AstStringLit node, Syt syt, StringBuilder sb)
 {
     sb.AppendLine("push constant {0}".StFormat(node.st.Length));
     sb.AppendLine("call String.new 1");
     sb.AppendLine("pop pointer 1");
     foreach (var ch in node.st)
     {
         sb.AppendLine("push pointer 1");
         sb.AppendLine("push constant {0}".StFormat((int)ch));
         sb.AppendLine("call String.appendChar 2");
     }
 }
예제 #11
0
 private void CompileBoolLit(AstBoolLit node, Syt syt, StringBuilder sb)
 {
     if (node.f)
     {
         sb.AppendLine("push constant 1");
         sb.AppendLine("neg");
     }
     else
     {
         sb.AppendLine("push constant 0");
     }
 }
예제 #12
0
        private void CompileUnOp(AstUnOp node, Syt syt, StringBuilder sb)
        {
            CompileRecursive(node.expr, syt, sb);
            switch (node.Kunop)
            {
            case KUnop.Minus: sb.AppendLine("neg"); break;

            case KUnop.Not: sb.AppendLine("not"); break;

            default:
                throw new ArgumentOutOfRangeException();
            }
        }
예제 #13
0
        private void CompileVarRef(AstVarRef node, Syt syt, StringBuilder sb)
        {
            var syte = syt.Lookup(node.StName);

            if (syte.Ksyte.FIn(Ksyte.Field, Ksyte.Arg, Ksyte.Var, Ksyte.Static))
            {
                sb.AppendLine("push {0} {1}".StFormat(StSegment(syte.Ksyte), syte.Isyte));
            }
            else
            {
                throw new Erparse(node, "not an rvalue");
            }
        }
예제 #14
0
        private void CompileWhile(AstWhile node, Syt syt, StringBuilder sb)
        {
            var lblWhile = Id("WHILE");
            var lblTrue  = Id("WHILE_TRUE");
            var lblEnd   = Id("WHILE_END");

            sb.AppendLine("label " + lblWhile);
            CompileRecursive(node.exprCond, syt, sb);
            sb.AppendLine("if-goto " + lblTrue);
            sb.AppendLine("goto " + lblEnd);

            sb.AppendLine("label " + lblTrue);
            CompileRecursive(node.rgstm, syt, sb);
            sb.AppendLine("goto " + lblWhile);

            sb.AppendLine("label " + lblEnd);
        }
예제 #15
0
        private void CompileIf(AstIf node, Syt syt, StringBuilder sb)
        {
            var lblTrue  = Id("IF_TRUE");
            var lblEndif = Id("IF_END");

            CompileRecursive(node.exprCond, syt, sb);
            sb.AppendLine("if-goto " + lblTrue);

            if (node.rgstmElse != null)
            {
                CompileRecursive(node.rgstmElse, syt, sb);
            }
            sb.AppendLine("goto " + lblEndif);

            sb.AppendLine("label " + lblTrue);
            CompileRecursive(node.rgstm, syt, sb);

            sb.AppendLine("label " + lblEndif);
        }
예제 #16
0
        private void CompileReturn(AstReturn node, Syt syt, StringBuilder sb)
        {
            var nodeFnc = node.NodeAncestor <AstSubroutine>();

            if (nodeFnc.Type.Ktype == Ktype.Void)
            {
                if (node.expr != null)
                {
                    throw new Erparse(node, "void method cannot return value");
                }
                sb.AppendLine("push constant 0");
            }
            else
            {
                if (node.expr == null)
                {
                    throw new Erparse(node, "void method must return value");
                }
                CompileRecursive(node.expr, syt, sb);
            }
            sb.AppendLine("return");
        }
예제 #17
0
        private void CompileBinOp(AstBinOp node, Syt syt, StringBuilder sb)
        {
            CompileRecursive(node.exprLeft, syt, sb);
            CompileRecursive(node.exprRight, syt, sb);

            switch (node.KBinop)
            {
                case KBinop.Plus: sb.AppendLine("add"); break;
                case KBinop.Minus: sb.AppendLine("sub"); break;

                case KBinop.And: sb.AppendLine("and"); break;
                case KBinop.Or: sb.AppendLine("or"); break;

                case KBinop.Lt: sb.AppendLine("lt"); break;
                case KBinop.Gt: sb.AppendLine("gt"); break;
                case KBinop.Eq: sb.AppendLine("eq"); break;

                case KBinop.Mul: sb.AppendLine("call Math.multiply 2"); break;
                case KBinop.Div: sb.AppendLine("call Math.divide 2"); break;
                default:
                    throw new ArgumentOutOfRangeException();
            }
        }
예제 #18
0
        private void CompileClass(AstClass node, Syt syt, StringBuilder sb)
        {
            syt.Add(Ksyte.Class, node.StName, node.StName);

            CompileRecursive(node.RgclassDecl, syt, sb);

            foreach (var astSubroutine in node.Rgsubroutine)
            {
                Ksyte ksyte;
                switch (astSubroutine.Ksubroutine)
                {
                case Ksubroutine.Constructor: ksyte = Ksyte.Constructor; break;

                case Ksubroutine.MemberFunction: ksyte = Ksyte.MemberFunction; break;

                case Ksubroutine.StaticFunction: ksyte = Ksyte.StaticFunction; break;

                default:
                    throw new ArgumentOutOfRangeException();
                }
                syt.Add(ksyte, astSubroutine.StName, null);
            }
            CompileRecursive(node.Rgsubroutine, syt, sb);
        }
예제 #19
0
 private void CompileClassDecl(AstClassDecl node, Syt syt, StringBuilder sb)
 {
     syt.Add(node.KClassDecl == KClassDecl.Field ? Ksyte.Field : Ksyte.Static, node.StName, node.Type.stType);
 }
예제 #20
0
 public Syt(Syt sytBase)
 {
     this.sytBase = sytBase;
 }
예제 #21
0
 private void CompileVarRef(AstVarRef node, Syt syt, StringBuilder sb)
 {
     var syte = syt.Lookup(node.StName);
     if (syte.Ksyte.FIn(Ksyte.Field, Ksyte.Arg, Ksyte.Var, Ksyte.Static))
         sb.AppendLine("push {0} {1}".StFormat(StSegment(syte.Ksyte), syte.Isyte));
     else
         throw new Erparse(node, "not an rvalue");
 }
예제 #22
0
 private void CompileUnOp(AstUnOp node, Syt syt, StringBuilder sb)
 {
     CompileRecursive(node.expr, syt, sb);
     switch (node.Kunop)
     {
         case KUnop.Minus: sb.AppendLine("neg"); break;
         case KUnop.Not: sb.AppendLine("not"); break;
         default:
             throw new ArgumentOutOfRangeException();
     }
 }
예제 #23
0
 private void CompileVarDecl(AstVarDecl node, Syt syt, StringBuilder sb)
 {
     syt.Add(node.FLocal ? Ksyte.Var : Ksyte.Arg, node.StName, node.Type.stType);
 }
예제 #24
0
 private void CompileStringLit(AstStringLit node, Syt syt, StringBuilder sb)
 {
     sb.AppendLine("push constant {0}".StFormat(node.st.Length));
     sb.AppendLine("call String.new 1");
     sb.AppendLine("pop pointer 1");
     foreach (var ch in node.st)
     {
         sb.AppendLine("push pointer 1");
         sb.AppendLine("push constant {0}".StFormat((int)ch));
         sb.AppendLine("call String.appendChar 2");
     }
 }
예제 #25
0
 private void CompileRecursive(AstNode node, Syt syt, StringBuilder sb)
 {
     if (node is AstBinOp) CompileBinOp((AstBinOp)node, syt, sb);
     else if (node is AstBoolLit) CompileBoolLit((AstBoolLit)node, syt, sb);
     else if (node is AstCall) CompileCall((AstCall)node, syt, sb);
     else if (node is AstClass) CompileClass((AstClass)node, syt, sb);
     else if (node is AstClassDecl) CompileClassDecl((AstClassDecl)node, syt, sb);
     else if (node is AstDo) CompileDo((AstDo)node, syt, sb);
     else if (node is AstDot) CompileDot((AstDot)node, syt, sb);
     else if (node is AstIf) CompileIf((AstIf)node, syt, sb);
     else if (node is AstIndex) CompileIndex((AstIndex)node, syt, sb);
     else if (node is AstIntLit) CompileIntLit((AstIntLit)node, syt, sb);
     else if (node is AstLet) CompileLet((AstLet)node, syt, sb);
     else if (node is AstNull) CompileNull((AstNull)node, syt, sb);
     else if (node is AstReturn) CompileReturn((AstReturn)node, syt, sb);
     else if (node is AstStringLit) CompileStringLit((AstStringLit)node, syt, sb);
     else if (node is AstSubroutine) CompileSubroutine((AstSubroutine)node, syt, sb);
     else if (node is AstThis) CompileThis((AstThis)node, syt, sb);
     else if (node is AstUnOp) CompileUnOp((AstUnOp)node, syt, sb);
     else if (node is AstVarDecl) CompileVarDecl((AstVarDecl)node, syt, sb);
     else if (node is AstVarRef) CompileVarRef((AstVarRef)node, syt, sb);
     else if (node is AstWhile) CompileWhile((AstWhile)node, syt, sb);
     else throw new ArgumentException("Unkonwn node " + node.GetType());
 }
예제 #26
0
 private void CompileThis(AstThis node, Syt syt, StringBuilder sb)
 {
     sb.AppendLine("push pointer 0");
 }
예제 #27
0
        private void CompileCall(AstCall node, Syt syt, StringBuilder sb)
        {
            var cparam = node.rgexprParam.Length;

            if (node.exprFunc is AstVarRef)
            {
                var nodeRef = (AstVarRef)node.exprFunc;
                var syte    = syt.Lookup(nodeRef.StName);

                switch (syte.Ksyte)
                {
                case Ksyte.StaticFunction:
                    break;

                case Ksyte.MemberFunction:
                    sb.AppendLine("push pointer 0");
                    cparam++;
                    break;

                default:
                    throw new Erparse(node, "unexpected ksyte " + syte.Ksyte);
                }

                foreach (var nodeParam in node.rgexprParam)
                {
                    CompileRecursive(nodeParam, syt, sb);
                }

                sb.AppendLine("call {0}.{1} {2}".StFormat(node.NodeAncestor <AstClass>().StName, syte.StName, cparam));
            }
            else if (node.exprFunc is AstDot)
            {
                var nodeDot = (AstDot)node.exprFunc;

                var syteLeft = syt.Lookup(nodeDot.varLeft.StName) ?? new Syte(Ksyte.Class, nodeDot.varLeft.StName, 0, nodeDot.varLeft.StName);

                if (!syteLeft.Ksyte.FIn(Ksyte.Arg, Ksyte.Field, Ksyte.Var, Ksyte.Static, Ksyte.Class))
                {
                    throw new Erparse(node, "unexpected ksyte " + syteLeft.Ksyte);
                }

                if (syteLeft.Ksyte.FIn(Ksyte.Arg, Ksyte.Field, Ksyte.Var, Ksyte.Static))
                {
                    cparam++;
                    CompileRecursive(nodeDot.varLeft, syt, sb);
                }

                Ksyte ksyteRight;
                if (syteLeft.Ksyte == Ksyte.Class && syteLeft.StName != node.NodeAncestor <AstClass>().StName)
                {
                    ksyteRight = Ksyte.StaticFunction /*constuctor???*/;
                }
                else
                {
                    var syte = syt.Lookup(nodeDot.varRight.StName);
                    ksyteRight = syte == null ? Ksyte.MemberFunction : syte.Ksyte;
                }

                switch (ksyteRight)
                {
                case Ksyte.Constructor:
                    if (syteLeft.Ksyte != Ksyte.Class)
                    {
                        throw new Erparse(node, "cannot call constructor on instance");
                    }
                    break;

                case Ksyte.StaticFunction:
                case Ksyte.MemberFunction:
                    break;

                default:
                    throw new Erparse(node, "unexpected ksyte " + ksyteRight);
                }

                foreach (var nodeParam in node.rgexprParam)
                {
                    CompileRecursive(nodeParam, syt, sb);
                }

                sb.AppendLine("call {0}.{1} {2}".StFormat(syteLeft.StType, nodeDot.varRight.StName, cparam));
            }
        }
예제 #28
0
 private void CompileNull(AstNull node, Syt syt, StringBuilder sb)
 {
     sb.AppendLine("push constant 0");
 }
예제 #29
0
 private void CompileDot(AstDot node, Syt syt, StringBuilder sb)
 {
     throw new NotImplementedException();
 }
예제 #30
0
 public Syt(Syt sytBase)
 {
     this.sytBase = sytBase;
 }
예제 #31
0
 private void CompileDo(AstDo node, Syt syt, StringBuilder sb)
 {
     CompileRecursive(node.exprCall, syt, sb);
     sb.AppendLine("pop temp 0");
 }
예제 #32
0
 private void CompileNull(AstNull node, Syt syt, StringBuilder sb)
 {
     sb.AppendLine("push constant 0");
 }
예제 #33
0
 private void CompileRecursive(IEnumerable<AstNode> rgnode, Syt syt, StringBuilder sb)
 {
     foreach (var node in rgnode)
         CompileRecursive(node, syt, sb);
 }
예제 #34
0
 private void CompileClassDecl(AstClassDecl node, Syt syt, StringBuilder sb)
 {
     syt.Add(node.KClassDecl == KClassDecl.Field ? Ksyte.Field : Ksyte.Static, node.StName, node.Type.stType);
 }
예제 #35
0
 private void CompileReturn(AstReturn node, Syt syt, StringBuilder sb)
 {
     var nodeFnc = node.NodeAncestor<AstSubroutine>();
     if (nodeFnc.Type.Ktype == Ktype.Void)
     {
         if (node.expr != null)
             throw new Erparse(node, "void method cannot return value");
         sb.AppendLine("push constant 0");
     }
     else
     {
         if (node.expr == null)
             throw new Erparse(node, "void method must return value");
         CompileRecursive(node.expr, syt, sb);
     }
     sb.AppendLine("return");
 }
예제 #36
0
 private void CompileDo(AstDo node, Syt syt, StringBuilder sb)
 {
     CompileRecursive(node.exprCall, syt, sb);
     sb.AppendLine("pop temp 0");
 }
예제 #37
0
        private void CompileSubroutine(AstSubroutine node, Syt syt, StringBuilder sb)
        {
            var sytFunc = new Syt(syt);

            sb.AppendLine("function {0} {1}".StFormat(node.FQName(), node.RgVarDeclDecl.Length));

            if (node.Ksubroutine == Ksubroutine.Constructor)
            {
                var csize = node.NodeAncestor<AstClass>().RgclassDecl.Length;
                sb.AppendLine("push constant {0}".StFormat(csize));
                sb.AppendLine("call Memory.alloc 1");
                sb.AppendLine("pop pointer 0");

            }
            else if (node.Ksubroutine == Ksubroutine.MemberFunction)
            {
                sb.AppendLine("push argument 0");
                sb.AppendLine("pop pointer 0");
                sytFunc.Add(Ksyte.Arg, "this", node.NodeAncestor<AstClass>().StName);
            }

            CompileRecursive(node.RgParam, sytFunc, sb);
            CompileRecursive(node.RgVarDeclDecl, sytFunc, sb);

            CompileRecursive(node.Body, sytFunc, sb);

            if (node.Type.Ktype == Ktype.Void)
            {
                sb.AppendLine("push constant 0");
                sb.AppendLine("return");
            }
        }
예제 #38
0
 private void CompileDot(AstDot node, Syt syt, StringBuilder sb)
 {
     throw new NotImplementedException();
 }
예제 #39
0
 private void CompileThis(AstThis node, Syt syt, StringBuilder sb)
 {
     sb.AppendLine("push pointer 0");
 }
예제 #40
0
        private void CompileIf(AstIf node, Syt syt, StringBuilder sb)
        {
            var lblTrue = Id("IF_TRUE");
            var lblEndif = Id("IF_END");

            CompileRecursive(node.exprCond, syt, sb);
            sb.AppendLine("if-goto " + lblTrue);

            if (node.rgstmElse != null)
                CompileRecursive(node.rgstmElse, syt, sb);
            sb.AppendLine("goto " + lblEndif);

            sb.AppendLine("label " + lblTrue);
            CompileRecursive(node.rgstm, syt, sb);

            sb.AppendLine("label " + lblEndif);
        }
예제 #41
0
 private void CompileVarDecl(AstVarDecl node, Syt syt, StringBuilder sb)
 {
     syt.Add(node.FLocal ? Ksyte.Var : Ksyte.Arg, node.StName, node.Type.stType);
 }
예제 #42
0
 private void CompileIndex(AstIndex node, Syt syt, StringBuilder sb)
 {
     CompileRecursive(node.exprLeft, syt, sb);
     CompileRecursive(node.exprRight, syt, sb);
     sb.AppendLine("add");
     sb.AppendLine("pop pointer 1");
     sb.AppendLine("push that 0");
 }
예제 #43
0
        private void CompileWhile(AstWhile node, Syt syt, StringBuilder sb)
        {
            var lblWhile = Id("WHILE");
            var lblTrue = Id("WHILE_TRUE");
            var lblEnd = Id("WHILE_END");

            sb.AppendLine("label " + lblWhile);
            CompileRecursive(node.exprCond, syt, sb);
            sb.AppendLine("if-goto " + lblTrue);
            sb.AppendLine("goto " + lblEnd);

            sb.AppendLine("label " + lblTrue);
            CompileRecursive(node.rgstm, syt, sb);
            sb.AppendLine("goto " + lblWhile);

            sb.AppendLine("label " + lblEnd);
        }
예제 #44
0
 private void CompileIntLit(AstIntLit node, Syt syt, StringBuilder sb)
 {
     sb.AppendLine("push constant " + Math.Abs(node.i));
     if (node.i < 0)
         sb.AppendLine("neg");
 }
예제 #45
0
        private void CompileClass(AstClass node, Syt syt, StringBuilder sb)
        {
            syt.Add(Ksyte.Class, node.StName, node.StName);

            CompileRecursive(node.RgclassDecl, syt, sb);

            foreach (var astSubroutine in node.Rgsubroutine)
            {
                Ksyte ksyte;
                switch (astSubroutine.Ksubroutine)
                {
                    case Ksubroutine.Constructor: ksyte = Ksyte.Constructor; break;
                    case Ksubroutine.MemberFunction: ksyte = Ksyte.MemberFunction; break;
                    case Ksubroutine.StaticFunction: ksyte = Ksyte.StaticFunction; break;
                    default:
                        throw new ArgumentOutOfRangeException();
                }
                syt.Add(ksyte, astSubroutine.StName, null);
            }
            CompileRecursive(node.Rgsubroutine, syt, sb);
        }
예제 #46
0
        private void CompileLet(AstLet node, Syt syt, StringBuilder sb)
        {
            CompileRecursive(node.exprRight, syt, sb);

            if (node.exprLeft is AstIndex)
            {
                var astIndex = (AstIndex) node.exprLeft;
                CompileRecursive(astIndex.exprLeft, syt, sb);
                CompileRecursive(astIndex.exprRight, syt, sb);
                sb.AppendLine("add");
                sb.AppendLine("pop pointer 1");
                sb.AppendLine("pop that 0");
                return;
            }

            if (node.exprLeft is AstVarRef)
            {
                var nodeVarRef = (AstVarRef) node.exprLeft;
                var syte = syt.Lookup(nodeVarRef.StName);
                if(syte.Ksyte.FIn(Ksyte.Field, Ksyte.Arg, Ksyte.Var, Ksyte.Static))
                    sb.AppendLine("pop {0} {1}".StFormat(StSegment(syte.Ksyte), syte.Isyte));
                return;
            }

            throw new Erparse(node, "not an lvalue");
        }
예제 #47
0
        private void CompileCall(AstCall node, Syt syt, StringBuilder sb)
        {
            var cparam = node.rgexprParam.Length;

            if (node.exprFunc is AstVarRef)
            {
                var nodeRef = (AstVarRef) node.exprFunc;
                var syte = syt.Lookup(nodeRef.StName);

                switch (syte.Ksyte)
                {
                    case Ksyte.StaticFunction:
                        break;
                    case Ksyte.MemberFunction:
                        sb.AppendLine("push pointer 0");
                        cparam++;
                        break;
                    default:
                        throw new Erparse(node, "unexpected ksyte " + syte.Ksyte);
                }

                foreach (var nodeParam in node.rgexprParam)
                    CompileRecursive(nodeParam, syt, sb);

                sb.AppendLine("call {0}.{1} {2}".StFormat(node.NodeAncestor<AstClass>().StName, syte.StName, cparam));
            }
            else if (node.exprFunc is AstDot)
            {
                var nodeDot = (AstDot) node.exprFunc;

                var syteLeft = syt.Lookup(nodeDot.varLeft.StName) ?? new Syte(Ksyte.Class, nodeDot.varLeft.StName, 0, nodeDot.varLeft.StName);

                if (!syteLeft.Ksyte.FIn(Ksyte.Arg, Ksyte.Field, Ksyte.Var, Ksyte.Static, Ksyte.Class))
                   throw new Erparse(node, "unexpected ksyte " + syteLeft.Ksyte);

                if (syteLeft.Ksyte.FIn(Ksyte.Arg, Ksyte.Field, Ksyte.Var, Ksyte.Static))
                {
                    cparam++;
                    CompileRecursive(nodeDot.varLeft, syt, sb);
                }

                Ksyte ksyteRight;
                if (syteLeft.Ksyte == Ksyte.Class && syteLeft.StName != node.NodeAncestor<AstClass>().StName)
                    ksyteRight = Ksyte.StaticFunction /*constuctor???*/;
                else
                {
                    var syte = syt.Lookup(nodeDot.varRight.StName);
                    ksyteRight = syte == null ? Ksyte.MemberFunction : syte.Ksyte;
                }

                switch (ksyteRight)
                {
                    case Ksyte.Constructor:
                        if (syteLeft.Ksyte != Ksyte.Class)
                            throw new Erparse(node, "cannot call constructor on instance");
                        break;
                    case Ksyte.StaticFunction:
                    case Ksyte.MemberFunction:
                        break;
                    default:
                        throw new Erparse(node, "unexpected ksyte " + ksyteRight);
                }

                foreach (var nodeParam in node.rgexprParam)
                    CompileRecursive(nodeParam, syt, sb);

                sb.AppendLine("call {0}.{1} {2}".StFormat(syteLeft.StType, nodeDot.varRight.StName, cparam));
            }
        }
예제 #48
0
 private void CompileRecursive(AstNode node, Syt syt, StringBuilder sb)
 {
     if (node is AstBinOp)
     {
         CompileBinOp((AstBinOp)node, syt, sb);
     }
     else if (node is AstBoolLit)
     {
         CompileBoolLit((AstBoolLit)node, syt, sb);
     }
     else if (node is AstCall)
     {
         CompileCall((AstCall)node, syt, sb);
     }
     else if (node is AstClass)
     {
         CompileClass((AstClass)node, syt, sb);
     }
     else if (node is AstClassDecl)
     {
         CompileClassDecl((AstClassDecl)node, syt, sb);
     }
     else if (node is AstDo)
     {
         CompileDo((AstDo)node, syt, sb);
     }
     else if (node is AstDot)
     {
         CompileDot((AstDot)node, syt, sb);
     }
     else if (node is AstIf)
     {
         CompileIf((AstIf)node, syt, sb);
     }
     else if (node is AstIndex)
     {
         CompileIndex((AstIndex)node, syt, sb);
     }
     else if (node is AstIntLit)
     {
         CompileIntLit((AstIntLit)node, syt, sb);
     }
     else if (node is AstLet)
     {
         CompileLet((AstLet)node, syt, sb);
     }
     else if (node is AstNull)
     {
         CompileNull((AstNull)node, syt, sb);
     }
     else if (node is AstReturn)
     {
         CompileReturn((AstReturn)node, syt, sb);
     }
     else if (node is AstStringLit)
     {
         CompileStringLit((AstStringLit)node, syt, sb);
     }
     else if (node is AstSubroutine)
     {
         CompileSubroutine((AstSubroutine)node, syt, sb);
     }
     else if (node is AstThis)
     {
         CompileThis((AstThis)node, syt, sb);
     }
     else if (node is AstUnOp)
     {
         CompileUnOp((AstUnOp)node, syt, sb);
     }
     else if (node is AstVarDecl)
     {
         CompileVarDecl((AstVarDecl)node, syt, sb);
     }
     else if (node is AstVarRef)
     {
         CompileVarRef((AstVarRef)node, syt, sb);
     }
     else if (node is AstWhile)
     {
         CompileWhile((AstWhile)node, syt, sb);
     }
     else
     {
         throw new ArgumentException("Unkonwn node " + node.GetType());
     }
 }