public override void FunctionDeclaration(Subroutine subroutine) { EmitStructDeclarationIfNotEmitted(); Output.WriteLine("__WORD {0} () {{", FormatSubroutineName(subroutine.Name)); EmitLocalsAndParameters(subroutine); ExtractParameters(subroutine); }
private void ExtractParameters(Subroutine subroutine) { foreach (Symbol param in subroutine.Parameters.Reverse()) { Output.WriteLine(" {0} = __POP();", param.Name); } }
public override void MethodDeclaration(Subroutine subroutine) { EmitStructDeclarationIfNotEmitted(); Output.WriteLine("__WORD {0} () {{", FormatSubroutineName(subroutine.Name)); EmitLocalsAndParameters(subroutine); //By convention, 'this' is the first parameter of the subroutine //call, so it's the last thing on the stack. Output.WriteLine(" __WORD THIS;"); Output.WriteLine(" THIS = __POP();"); ExtractParameters(subroutine); }
private void EmitLocalsAndParameters(Subroutine subroutine) { foreach (Symbol localVar in subroutine.Locals) { Output.WriteLine(" __WORD {0};", localVar.Name); } foreach (Symbol param in subroutine.Parameters) { Output.WriteLine(" __WORD {0};", param.Name); } }
public override void ConstructorDeclaration(Subroutine subroutine) { EmitStructDeclarationIfNotEmitted(); Output.WriteLine("__WORD {0} () {{", FormatSubroutineName(subroutine.Name)); EmitLocalsAndParameters(subroutine); Output.WriteLine(" __WORD THIS;"); //A constructor must allocate memory for its class and //assign the result to the THIS local variable. Output.WriteLine(" THIS = (__WORD) __ALLOC({0}*sizeof(__WORD));", GetClassSizeInWords()); ExtractParameters(subroutine); }
private void ParseSubDecl() { Contract.Requires(IsNextTokenSubDecl()); Token subKind = NextToken(); Token returnType = NextToken(); Token subName = NextToken(); if (subKind.Type != TokenType.Keyword || !new[] { "constructor", "method", "function" }.Contains(subKind.Value)) { ThrowCompilationException("Expected: 'constructor', 'method', or 'function', but got: " + subKind.Value); } if (returnType.Type != TokenType.Keyword && returnType.Type != TokenType.Ident) { ThrowCompilationException("Invalid return type '" + returnType.Value + "'"); } if (subName.Type != TokenType.Ident) { ThrowCompilationException("Invalid subroutine name '" + subName.Value + "'"); } _currentSub = new Subroutine( (SubroutineKind)Enum.Parse(typeof(SubroutineKind), subKind.Value, ignoreCase: true), _currentClassName, subName.Value, returnType.Value); if (_currentSub.Kind == SubroutineKind.Constructor && _currentSub.ReturnType != _currentClassName) { ThrowCompilationException("Constructor must return '" + _currentClassName + "'"); } Match(new Token(TokenType.Symbol, "(")); ParseFormalParamList(); Match(new Token(TokenType.Symbol, ")")); //NOTE: We notify the code generator of the new subroutine only //after we have its local variable declarations. ParseSubBody(); _currentSub = null; _methodSymTable.Clear(); }
public override void FunctionDeclaration(Subroutine subroutine) { Output.WriteLine( "FUNCTION {0}.{1}", subroutine.ClassName, subroutine.Name); }
public abstract void MethodDeclaration(Subroutine subroutine);
public abstract void ConstructorDeclaration(Subroutine subroutine);
public abstract void FunctionDeclaration(Subroutine subroutine);
public override void ConstructorDeclaration(Subroutine subroutine) { Output.WriteLine( "CONSTRUCTOR {0}.{1}", subroutine.ClassName, subroutine.Name); }
public override void MethodDeclaration(Subroutine subroutine) { Output.WriteLine( "METHOD {0}.{1}", subroutine.ClassName, subroutine.Name); }
private void ParseSubDecl() { Contract.Requires(IsNextTokenSubDecl()); Token subKind = NextToken(); Token returnType = NextToken(); Token subName = NextToken(); if (subKind.Type != TokenType.Keyword || !new[]{"constructor", "method", "function"}.Contains(subKind.Value)) { ThrowCompilationException("Expected: 'constructor', 'method', or 'function', but got: " + subKind.Value); } if (returnType.Type != TokenType.Keyword && returnType.Type != TokenType.Ident) { ThrowCompilationException("Invalid return type '" + returnType.Value + "'"); } if (subName.Type != TokenType.Ident) { ThrowCompilationException("Invalid subroutine name '" + subName.Value + "'"); } _currentSub = new Subroutine( (SubroutineKind) Enum.Parse(typeof (SubroutineKind), subKind.Value, ignoreCase: true), _currentClassName, subName.Value, returnType.Value); if (_currentSub.Kind == SubroutineKind.Constructor && _currentSub.ReturnType != _currentClassName) { ThrowCompilationException("Constructor must return '" + _currentClassName + "'"); } Match(new Token(TokenType.Symbol, "(")); ParseFormalParamList(); Match(new Token(TokenType.Symbol, ")")); //NOTE: We notify the code generator of the new subroutine only //after we have its local variable declarations. ParseSubBody(); _currentSub = null; _methodSymTable.Clear(); }