private IEnumerable <AstSubroutine> ParseRgSubroutine() { while (FCurrent(Ktoken.Constructor) || FCurrent(Ktoken.Function) || FCurrent(Ktoken.Method)) { var subroutine = new AstSubroutine(); subroutine.Ksubroutine = FCurrent(Ktoken.Constructor) ? Ksubroutine.Constructor : FCurrent(Ktoken.Function) ? Ksubroutine.StaticFunction : Ksubroutine.MemberFunction; NextToken(); subroutine.Type = Accept(Ktoken.Void) ? new AstType { Ktype = Ktype.Void, stType = "void" } : ParseType(); subroutine.StName = Expect(Ktoken.Id).St; subroutine.RgParam = ParseParamDefList().ToArray(); Expect(Ktoken.Lbrace); subroutine.RgVarDeclDecl = ParseVarDeclList().ToArray(); subroutine.Body = ParseStatementList().ToArray(); Expect(Ktoken.Rbrace); yield return(subroutine); } }
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"); } }