public void WritePopIdentifier(Identifier identifier) { if (identifier.Kind == Kind.Var) { this.WritePop(Segment.Local, identifier.Index); } else if (identifier.Kind == Kind.Arg) { this.WritePop(Segment.Argument, identifier.Index); } else if (identifier.Kind == Kind.Static) { // p.131 static variables are shared by all functions in the same vm file. this.WritePop(Segment.Static, identifier.Index); } else if (identifier.Kind == Kind.Field) { this.WritePop(Segment.This, identifier.Index); } }
public void WritePushIdentifier(Identifier identifier) { // dont think this is necessary see page 136 // ithink the vm handles local variables - then you just "pop local 1" etc to use them if(identifier.Kind == Kind.Var) { this.WritePush(Segment.Local, identifier.Index); } else if(identifier.Kind == Kind.Arg) { this.WritePush(Segment.Argument, identifier.Index); } else if (identifier.Kind == Kind.Static) { // p.131 static variables are shared by all functions in the same vm file. this.WritePush(Segment.Static, identifier.Index); } else if (identifier.Kind == Kind.Field) { this.WritePush(Segment.This, identifier.Index); } }
/// <summary> /// Builds an identifer obj and also identifier. /// Only use this method for compiling class variables and subroutine variables /// Not parameter lists! /// </summary> /// <param name="parent">The parent.</param> /// <returns></returns> private void CompileClassOrSubRoutineLevelVarDeclarationAndAddToSymbolTable(XElement parent) { Pair<string, string> kindToken = this.CompileTerminal(parent); Pair<string, string> typeToken = this.CompileTerminal(parent); Pair<string, string> nameToken = this.classTokens.Pop(); Identifier identifier = new Identifier(); identifier.Kind = (Kind)Enum.Parse(typeof(Kind), kindToken.Value2, true); identifier.Name = nameToken.Value2; identifier.Type = typeToken.Value2; identifier.Usage = IdentifierUsage.Defined; this.symbolTable.Define(identifier); this.CreateIdentifierElementWithAttributes(parent, identifier, nameToken); // check for comma, i.e comma separated list of variables if (this.classTokens.Peek().Value2 == ",") { // compile the comma this.CompileTerminal(parent); while (this.classTokens.Peek().Value2 != ";") { Pair<string, string> commaSeparatedIdentifierToken = this.classTokens.Pop(); // set the next identifier in comma separated list to same type kind etc as fisrt Identifier commaSeparatedIdentier = new Identifier(); commaSeparatedIdentier.Kind = identifier.Kind; commaSeparatedIdentier.Type = identifier.Type; commaSeparatedIdentier.Name = commaSeparatedIdentifierToken.Value2; commaSeparatedIdentier.Usage = IdentifierUsage.Defined; this.symbolTable.Define(commaSeparatedIdentier); this.CreateIdentifierElementWithAttributes(parent, commaSeparatedIdentier, commaSeparatedIdentifierToken); if (this.classTokens.Peek().Value2 == ",") { // compile comma this.CompileTerminal(parent); } } } // compile the ending ; this.CompileTerminal(parent); }
private void CreateIdentifierElementWithAttributes(XElement parent, Identifier identifier, Pair<string, string> identifierToken) { // quick hack with the category - if the identifier is not a method or a class name the category will be the same as kind // see page p243's confusing spec. parent.Add(new XElement(identifierToken.Value1, identifierToken.Value2, new XAttribute("type", identifier.Type), new XAttribute("usage", identifier.Usage), new XAttribute("kind", identifier.Kind), new XAttribute("category", identifier.Kind), new XAttribute("index", identifier.Index))); }
/// <summary> /// Compiles the parameter list of a method/function/constructor /// </summary> /// <param name="parentElement">The parent element.</param> private void CompileParameterList(XElement parentElement) { // add param list as child XElement parameterList = new XElement("parameterList"); parentElement.Add(parameterList); // add the params while (this.classTokens.Peek().Value2 != ")") { Pair<string, string> token = null; Identifier identifier = new Identifier(); identifier.Kind = Kind.Arg; for (int i = 0; i <= 2; i++) { if (this.classTokens.Peek().Value2 != ")") { token = this.classTokens.Pop(); if (i == 0) { identifier.Type = token.Value2; parameterList.Add(new XElement(token.Value1, token.Value2)); } else if (i == 1) { identifier.Name = token.Value2; identifier.Usage = IdentifierUsage.Defined; this.symbolTable.Define(identifier); this.CreateIdentifierElementWithAttributes(parameterList, identifier, token); } else if (i == 2) { //add the comma parameterList.Add(new XElement(token.Value1, token.Value2)); } } } } }
public readonly Identifier type; // identifier (variable / method / operator / etc...) public Piece(string name, Identifier type) { this.name = name; this.type = type; }
/// <summary> /// Compiles the parameter list of a method/function/constructor /// </summary> /// <param name="parentElement">The parent element.</param> private void CompileParameterList(bool isInstanceMethod) { // add the params if (isInstanceMethod) { Identifier hiddenThisArg = new Identifier(); hiddenThisArg.Type = "this"; hiddenThisArg.Name = "this"; hiddenThisArg.Usage = IdentifierUsage.Defined; hiddenThisArg.Kind = Kind.Arg; this.symbolTable.Define(hiddenThisArg); } while (this.classTokens.Peek().Value2 != ")") { Pair<string, string> token = null; Identifier identifier = new Identifier(); identifier.Kind = Kind.Arg; for (int i = 0; i <= 2; i++) { if (this.classTokens.Peek().Value2 != ")") { token = this.classTokens.Pop(); if (i == 0) { identifier.Type = token.Value2; } else if (i == 1) { identifier.Name = token.Value2; identifier.Usage = IdentifierUsage.Defined; this.symbolTable.Define(identifier); } else if (i == 2) { //add the comma - relic from xml output //parameterList.Add(new XElement(token.Value1, token.Value2)); } } } } }