コード例 #1
0
ファイル: Compiler.cs プロジェクト: robotii/sophielang
        // A map literal.
        private static void Map(Compiler c, bool allowAssignment)
        {
            // Load the Map class.
            int mapClassSymbol = c._parser.Module.Variables.FindIndex(v => v.Name == "Map");
            c.EmitShortArg(Instruction.LoadModuleVar, mapClassSymbol);

            // Instantiate a new map.
            c.CallMethod(0, "<instantiate>");

            // Compile the map elements. Each one is compiled to just invoke the
            // subscript setter on the map.
            if (c.Peek() != TokenType.RightBrace)
            {
                do
                {
                    c.IgnoreNewlines();

                    // Push a copy of the map since the subscript call will consume it.
                    c.Emit(Instruction.Dup);

                    // The key.
                    c.ParsePrecedence(false, Precedence.Primary);
                    c.Consume(TokenType.Colon, "Expect ':' after map key.");

                    // The value.
                    c.Expression();

                    c.CallMethod(2, "[_]=(_)");

                    // Discard the result of the setter call.
                    c.Emit(Instruction.Pop);
                } while (c.Match(TokenType.Comma));
            }

            // Allow newlines before the closing '}'.
            c.IgnoreNewlines();
            c.Consume(TokenType.RightBrace, "Expect '}' after map entries.");
        }
コード例 #2
0
ファイル: Compiler.cs プロジェクト: robotii/sophielang
        // A list literal.
        private static void List(Compiler c, bool allowAssignment)
        {
            // Load the List class.
            int listClassSymbol = c._parser.Module.Variables.FindIndex(v => v.Name == "List");
            //ASSERT(listClassSymbol != -1, "Should have already defined 'List' variable.");
            c.EmitShortArg(Instruction.LoadModuleVar, listClassSymbol);

            // Instantiate a new list.
            c.CallMethod(0, "<instantiate>");

            // Compile the list elements. Each one compiles to a ".add()" call.
            if (c.Peek() != TokenType.RightBracket)
            {
                do
                {
                    c.IgnoreNewlines();

                    // Push a copy of the list since the add() call will consume it.
                    c.Emit(Instruction.Dup);

                    // The element.
                    c.Expression();
                    c.CallMethod(1, "add(_)");

                    // Discard the result of the add() call.
                    c.Emit(Instruction.Pop);
                } while (c.Match(TokenType.Comma));
            }

            // Allow newlines before the closing ']'.
            c.IgnoreNewlines();
            c.Consume(TokenType.RightBracket, "Expect ']' after list elements.");
        }
コード例 #3
0
ファイル: Compiler.cs プロジェクト: robotii/sophielang
        private static void Field(Compiler c, bool allowAssignment)
        {
            // Initialize it with a fake value so we can keep parsing and minimize the
            // number of cascaded errors.
            int field = 255;

            ClassCompiler enclosingClass = c.GetEnclosingClass();

            if (enclosingClass == null)
            {
                c.Error("Cannot reference a field outside of a class definition.");
            }
            else if (enclosingClass.IsStaticMethod)
            {
                c.Error("Cannot use an instance field in a static method.");
            }
            else
            {
                // Look up the field, or implicitly define it.
                string fieldName = c._parser.Source.Substring(c._parser.Previous.Start, c._parser.Previous.Length);
                field = enclosingClass.Fields.IndexOf(fieldName);
                if (field < 0)
                {
                    enclosingClass.Fields.Add(fieldName);
                    field = enclosingClass.Fields.IndexOf(fieldName);
                }

                if (field >= MaxFields)
                {
                    c.Error(string.Format("A class can only have {0} fields.", MaxFields));
                }
            }

            // If there's an "=" after a field name, it's an assignment.
            bool isLoad = true;
            if (c.Match(TokenType.Eq))
            {
                if (!allowAssignment) c.Error("Invalid assignment.");

                // Compile the right-hand side.
                c.Expression();
                isLoad = false;
            }

            // If we're directly inside a method, use a more optimal instruction.
            if (c._parent != null && c._parent._enclosingClass == enclosingClass)
            {
                c.EmitByteArg(isLoad ? Instruction.LoadFieldThis : Instruction.StoreFieldThis,
                            field);
            }
            else
            {
                c.LoadThis();
                c.EmitByteArg(isLoad ? Instruction.LoadField : Instruction.StoreField, field);
            }
        }
コード例 #4
0
ファイル: Compiler.cs プロジェクト: robotii/sophielang
 // A parenthesized expression.
 private static void Grouping(Compiler c, bool allowAssignment)
 {
     c.Expression();
     c.Consume(TokenType.RightParen, "Expect ')' after expression.");
 }
コード例 #5
0
ファイル: Compiler.cs プロジェクト: robotii/sophielang
        // Subscript or "array indexing" operator like `foo[bar]`.
        private static void Subscript(Compiler c, bool allowAssignment)
        {
            Signature signature = new Signature { Name = "", Length = 0, Type = SignatureType.Subscript, Arity = 0 };

            // Parse the argument list.
            c.FinishArgumentList(signature);
            c.Consume(TokenType.RightBracket, "Expect ']' after arguments.");

            if (c.Match(TokenType.Eq))
            {
                if (!allowAssignment) c.Error("Invalid assignment.");

                signature.Type = SignatureType.SubscriptSetter;

                // Compile the assigned value.
                c.ValidateNumParameters(++signature.Arity);
                c.Expression();
            }

            c.CallSignature(Instruction.Call0, signature);
        }