public override void Assignment(Token varName, bool withArrayIndex) { //This is slightly tricky. We need to have the address of the //variable to which we're doing the assignment on the stack, //and then everything is really easy. If it's an array, we need //the address of the array element to which we're doing the //assignment (its index is on the stack following the LHS value). if (MethodSymTable.HasSymbol(varName.Value)) { Symbol symbol = MethodSymTable.GetSymbol(varName.Value); Contract.Assert(symbol.Kind == SymbolKind.Local || symbol.Kind == SymbolKind.Parameter); Output.WriteLine(" __PUSH((__WORD)&{0});", symbol.Name); } else { Contract.Assert(ClassSymTable.HasSymbol(varName.Value)); Symbol symbol = ClassSymTable.GetSymbol(varName.Value); if (symbol.Kind == SymbolKind.Static) { Output.WriteLine(" __PUSH((__WORD)&{0});", FormatStaticName(symbol.Name)); } else if (symbol.Kind == SymbolKind.Field) { Output.WriteLine(" __PUSH((__WORD)&((({0}*)THIS)->{1}));", _currentClassName, symbol.Name); } } //If it's an array, obtain the address of the right element by //adding the index which is on the stack. We need a scratch //location because issuing two __POP() calls in the same statement //does not guarantee left-to-right evaluation. if (withArrayIndex) { //The array address is now on the stack, but we really need the //address of the first element. Hence the dereference: Output.WriteLine(" __SCRATCH2 = *(__WORD*)__POP();"); //This is the RHS value that we ought to put in the array element: Output.WriteLine(" __SCRATCH1 = __POP();"); //Finally, the top of the stack contains the value of the array //indexing expression, i.e. the element index: Output.WriteLine(" * ( ((__WORD*)__SCRATCH2) + __POP() ) = __SCRATCH1;"); } else { Output.WriteLine(" __SCRATCH1 = __POP();"); //This is the LHS Output.WriteLine(" * ((__WORD*)__SCRATCH1) = __POP();"); } }
public override void VariableRead(Token varName, bool withArrayIndex) { //Put the value of the variable on the top of the stack. If it's //an array, the value is the address of the array's first element. if (MethodSymTable.HasSymbol(varName.Value)) { Symbol symbol = MethodSymTable.GetSymbol(varName.Value); Contract.Assert(symbol.Kind == SymbolKind.Local || symbol.Kind == SymbolKind.Parameter); Output.WriteLine(" __PUSH({0});", symbol.Name); } else { Contract.Assert(ClassSymTable.HasSymbol(varName.Value)); Symbol symbol = ClassSymTable.GetSymbol(varName.Value); if (symbol.Kind == SymbolKind.Static) { Output.WriteLine(" __PUSH({0});", FormatStaticName(symbol.Name)); } else if (symbol.Kind == SymbolKind.Field) { Output.WriteLine(" __PUSH((({0}*)THIS)->{1});", _currentClassName, symbol.Name); } } //If it's an array, dereference it using []. We need a scratch //location because issuing two __POP() calls in the same statement //does not guarantee left-to-right evaluation. if (withArrayIndex) { Output.WriteLine(" __SCRATCH1 = __POP();"); Output.WriteLine(" __PUSH( ((__WORD*)__SCRATCH1)[ __POP() ] );"); } }