Exemplo n.º 1
0
        internal static string VMString(this VMWriter.Segment seg)
        {
            switch (seg)
            {
            case VMWriter.Segment.CONST:
                return("constant");

            case VMWriter.Segment.ARG:
                return("argument");

            case VMWriter.Segment.LOCAL:
                return("local");

            case VMWriter.Segment.POINTER:
                return("pointer");

            case VMWriter.Segment.STATIC:
                return("static");

            case VMWriter.Segment.TEMP:
                return("temp");

            case VMWriter.Segment.THAT:
                return("that");

            case VMWriter.Segment.THIS:
                return("this");

            default:
                return("");
            }
        }
Exemplo n.º 2
0
 public void emitLetStatement(VMWriter.Segment seg, int num)
 {
     // if we're popping to an array object, we need to grab the THAT pointer off the stack first
     if (seg == VMWriter.Segment.THAT)
     {
         emitPopSecondStackValue(VMWriter.Segment.POINTER, 1);
     }
     writer.WritePop(seg, num);
 }
Exemplo n.º 3
0
 public void emitArrayIndex(VMWriter.Segment arraySeg, int arrayIndex, bool isLetStatement = false)
 {
     writer.WritePush(arraySeg, arrayIndex);
     writer.WriteArithmetic(VMWriter.ArithCommand.add);
     // TODO: this needs to change; leave it on the stack, perform other operations, then pop when needed.
     if (!isLetStatement)
     {
         writer.WritePop(VMWriter.Segment.POINTER, 1);
     }
 }
Exemplo n.º 4
0
 public static string VM_ToString(this VMWriter.Segment segment)
 {
     if (segment == VMWriter.Segment.CONST)
     {
         return("constant");
     }
     else if (segment == VMWriter.Segment.ARG)
     {
         return("argument");
     }
     else
     {
         return(segment.ToString().ToLower());
     }
 }
        public void CompileLet()
        {
            if (CheckTokenSequence(out validatedTokens, "let", "?identifier"))
            {
                VMWriter.Segment seg = emitter.GetVarSegment(symbolTable.KindOf(tokenizer.TokenValue));
                int segIndex         = symbolTable.IndexOf(tokenizer.TokenValue);
                if (tokenizer.PeakAhead().Value == "[")
                {
                    // CompileArrayIndex will set the THAT pointer to the location of the array item, so the destination becomes (that, 0)
                    CompileArrayIndex();
                    seg      = VMWriter.Segment.THAT;
                    segIndex = 0;
                }

                CheckTokenSequence(out validatedTokens, "=");
                CompileExpression();
                tokenizer.Advance();
                emitter.emitLetStatement(seg, segIndex);
            }
        }
Exemplo n.º 6
0
 public void emitPopSecondStackValue(VMWriter.Segment seg, int segIndex)
 {
     writer.WritePop(VMWriter.Segment.TEMP, 0);
     writer.WritePop(seg, segIndex);
     writer.WritePush(VMWriter.Segment.TEMP, 0);
 }
Exemplo n.º 7
0
 public void emitTerm(VMWriter.Segment seg, int value)
 {
     writer.WritePush(seg, value);
 }
        /// <summary>
        /// Compiles an individual term of an expression.  The current token should already be the first token of the term (which may be a "(" denoting an enclosed expression) before calling.
        /// </summary>
        public void CompileTerm()
        {
            bool isUnaryOperator = (tokenizer.CurrentToken.IsBinOperator() && tokenizer.PeakAhead().IsUnaryOperator());

            switch (tokenizer.TokenType)
            {
            case JackToken.TokenType.integerConstant:
                emitter.emitTerm(VMWriter.Segment.CONST, int.Parse(tokenizer.TokenValue));
                break;

            case JackToken.TokenType.stringConstant:
                emitter.emitStringConstant(tokenizer.TokenValue);
                break;

            case JackToken.TokenType.identifier:
                VMWriter.Segment seg = emitter.GetVarSegment(symbolTable.KindOf(tokenizer.TokenValue));
                int segIndex         = symbolTable.IndexOf(tokenizer.TokenValue);
                if (segIndex != -1 && tokenizer.PeakAhead().Value != "[")
                {
                    emitter.emitTerm(seg, segIndex);
                }
                break;

            case JackToken.TokenType.keyword:
                switch (tokenizer.TokenValue)
                {
                case "true":
                case "false":
                case "null":
                    emitter.emitBooleanConstant(tokenizer.TokenValue);
                    break;

                case "this":
                    emitter.emitTerm(VMWriter.Segment.POINTER, 0);
                    break;
                }
                break;

            case JackToken.TokenType.symbol:
                // TODO: does this actually need to be here?  Seems to be only parentheses and unaries that actually make it this far.
                break;
            }

            if (tokenizer.CurrentToken.Value == "(")
            {
                CompileExpression();
                CheckTokenSequence(out validatedTokens, ")");
            }

            else if (tokenizer.CurrentToken.IsUnaryOperator())
            {
                string unaryOp = tokenizer.TokenValue;
                tokenizer.Advance();
                CompileTerm();
                emitter.emitOperator(unaryOp);
            }
            else
            {
                // one token look ahead is needed to determine if the term is a single identifier, an array with index, or an object with a sub call
                switch (tokenizer.PeakAhead().Value)
                {
                case "[":
                    CompileArrayIndex();
                    emitter.emitTerm(VMWriter.Segment.THAT, 0);
                    break;

                case ".":
                    CompileSubroutineCall();
                    break;

                default:
                    break;
                }
            }
        }