Beispiel #1
0
 public TermExpression(
     Token start,
     Expression left,
     Keyword oper,
     Expression right)
     : base(start)
 {
     this.Left = left;
     this.Operator = oper;
     this.Right = right;
 }
Beispiel #2
0
 public VariableDeclaration(
     Token start, 
     IEnumerable<string> variableNames, 
     TypeReference type,
     Expression initExpression)
     : base(start)
 {
     this.type = type;
     this.variableNames.AddRange(variableNames);
     this.InitExpression = initExpression;
 }
Beispiel #3
0
        private bool ParseAddressExpression(TokenReader reader, out Expression expression)
        {
            expression = null;
            Token tok = reader.Peek();
            if (!this.Expect(reader, Keyword.Address))
            {
                return false;
            }

            ReferenceExpression refExpr = null;
            if (!this.ParseReferenceExpression(reader, out refExpr))
            {
                return false;
            }

            expression = new AddressExpression(tok, refExpr);
            return true;
        }
Beispiel #4
0
        private bool ParseTermExpression(TokenReader reader, out Expression result)
        {
            result = null;
            Token start = reader.Peek();
            Expression outer = null;
            if (!this.ParseFactorExpression(reader, out outer))
            {
                return false;
            }

            Token tok = reader.Peek();
            while (tok.Is(Keyword.Star) || tok.Is(Keyword.Slash) || tok.Is(Keyword.Div) || tok.Is(Keyword.And) || tok.Is(Keyword.Mod))
            {
                reader.Read();
                Expression factor = null;
                if (!this.ParseFactorExpression(reader, out factor))
                {
                    return false;
                }

                outer = new TermExpression(start, outer, ((KeywordToken)tok).Value, factor);
                tok = reader.Peek();
            }

            result = outer;
            return true;
        }
Beispiel #5
0
        private bool ParseSimpleExpression(TokenReader reader, out Expression result)
        {
            Token start = reader.Peek();
            result = null;
            Expression outer = null;
            if (!this.ParseTermExpression(reader, out outer))
            {
                return false;
            }

            Token tok = reader.Peek();
            while (tok.Is(Keyword.Plus) || tok.Is(Keyword.Minus) || tok.Is(Keyword.Or))
            {
                reader.Read();
                Expression term = null;
                if (!this.ParseTermExpression(reader, out term))
                {
                    return false;
                }

                outer = new SimpleExpression(start, outer, ((KeywordToken)tok).Value, term);

                tok = reader.Peek();
            }

            result = outer;
            return true;
        }
Beispiel #6
0
        private bool ParseNotExpression(TokenReader reader, out Expression expression)
        {
            expression = null;
            Token start = reader.Peek();
            if (!this.Expect(reader, Keyword.Not))
            {
                return false;
            }

            Expression inner = null;
            if (!this.ParseFactorExpression(reader, out inner))
            {
                return false;
            }

            expression = new NotExpression(start, inner);
            return true;
        }
Beispiel #7
0
        private bool ParseNewExpression(TokenReader reader, out Expression expression)
        {
            expression = null;
            Token start = reader.Peek();
            if (!this.Expect(reader, Keyword.New))
            {
                return false;
            }

            TypeReference typeRef = null;
            if (!this.ParseTypeReference(reader, out typeRef))
            {
                return false;
            }

            List<Expression> args = new List<Expression>();
            Token tok = reader.Peek();
            if (tok.Is(Keyword.LeftParen))
            {
                reader.Read();
                tok = reader.Peek();
                while (tok != null && !tok.Is(Keyword.RightParen))
                {
                    Expression arg = null;
                    if (!this.ParseExpression(reader, out arg))
                    {
                        return false;
                    }

                    args.Add(arg);
                    tok = reader.Peek();
                    if (!tok.Is(Keyword.Comma))
                    {
                        break;
                    }
                    else
                    {
                        tok = reader.Read();
                    }
                }

                if (!this.Expect(reader, Keyword.RightParen))
                {
                    return false;
                }
            }

            expression = new NewExpression(start, typeRef, args);
            return true;
        }
Beispiel #8
0
        private bool TryEmitExpression(
            Expression expression, 
            CompilerContext context, 
            Scope scope, 
            MethodImpl method, 
            out TypeDefinition valueType)
        {
            LiteralExpression literalExpr = expression as LiteralExpression;
            if (literalExpr != null)
            {
                return this.TryEmitLiteralExpression(literalExpr, context, scope, method, out valueType);
            }

            CallReferenceExpression callExpr = expression as CallReferenceExpression;
            if (callExpr != null)
            {
                int argSize = 0;
                int argStatementStart = method.Statements.Count;
                Expression[] arguments = callExpr.Arguments.ToArray();
                List<TypeDefinition> argTypes = new List<TypeDefinition>();
                for (int i = arguments.Length - 1; i >= 0; i--)
                {
                    TypeDefinition argType = null;
                    if (!this.TryEmitExpression(arguments[i], context, scope, method, out argType))
                    {
                        valueType = null;
                        return false;
                    }

                    argTypes.Insert(0, argType);
                    argSize += ((argType.Size + 3) / 4) * 4;
                    this.PushResult(method, argType);
                }

                string callLoc = null;
                TypeDefinition storageType = null;
                MethodInfo calleeMethod = null;
                if (!this.TryEmitReference(callExpr.Inner, context, scope, method, out callLoc, out storageType, out calleeMethod))
                {
                    valueType = null;
                    return false;
                }

                // fix up calling overloads here vs. inside TryEmitReference.
                if (calleeMethod != null)
                {
                    MethodInfo overload = calleeMethod.Type.FindMethod(calleeMethod.Name, argTypes);
                    if (overload != null)
                    {
                        if (string.CompareOrdinal(calleeMethod.MangledName, callLoc) == 0)
                        {
                            callLoc = overload.MangledName;
                        }

                        method.Module.AddProto(overload);
                        calleeMethod = overload;
                        storageType = overload.ReturnType;
                    }
                }

                if (storageType != null)
                {
                    if (callLoc == null)
                    {
                        // must be a constructor call.
                        MethodInfo constructor = storageType.FindConstructor(argTypes);
                        if (constructor == null)
                        {
                            string message = string.Format(
                                System.Globalization.CultureInfo.CurrentCulture,
                                Properties.Resources.CodeGenerator_CannotFindConstructor,
                                storageType.FullName);
                            log.Write(new Message(
                                callExpr.Start.Path,
                                callExpr.Start.Line,
                                callExpr.Start.Column,
                                Severity.Error,
                                message));
                            valueType = null;
                            return false;
                        }

                        calleeMethod = constructor;
                        callLoc = constructor.MangledName;
                        method.Module.AddProto(constructor);

                        // create room on the stack for the result.
                        AsmStatement resultPush = new AsmStatement { Instruction = string.Format("sub esp,{0}", storageType.Size) };
                        method.Statements.Insert(argStatementStart, resultPush);

                        // push the ref to the storage for the class on the stack.
                        method.Statements.Add(new AsmStatement { Instruction = string.Format("lea eax,[esp+{0}]", argSize) });
                        method.Statements.Add(new AsmStatement { Instruction = "push eax" });
                    }
                    else if (storageType.IsClass || !storageType.IsFloatingPoint && storageType.Size > 8)
                    {
                        // create room on the stack for the result.
                        AsmStatement resultPush = new AsmStatement { Instruction = string.Format("sub esp,{0}", storageType.Size) };
                        method.Statements.Insert(argStatementStart, resultPush);

                        // push the ref to the storage for the class on the stack.
                        method.Statements.Add(new AsmStatement { Instruction = string.Format(
                            "lea ebx,[esp+{0}]",
                            calleeMethod.IsStatic ? argSize : argSize + 4) });
                        method.Statements.Add(new AsmStatement { Instruction = "push ebx" });
                        argSize += 4;
                    }
                }

                if (calleeMethod.IsVirtual && callExpr.Inner.UseVirtualDispatch)
                {
                    FieldInfo vtablePtr = calleeMethod.Type.GetVTablePointer();
                    if (string.CompareOrdinal(callLoc, "[eax]") != 0)
                    {
                        method.Statements.Add(new AsmStatement { Instruction = string.Format("lea eax,{0}", callLoc) });
                    }

                    if (vtablePtr.Offset > 0)
                    {
                        method.Statements.Add(new AsmStatement { Instruction = string.Format("add eax,{0}", vtablePtr.Offset) });
                    }

                    method.Statements.Add(new AsmStatement { Instruction = "mov ecx,[eax]" });
                    if (calleeMethod.VTableIndex > 0)
                    {
                        method.Statements.Add(new AsmStatement { Instruction = string.Format("add ecx,{0}", calleeMethod.VTableIndex * 4) });
                    }

                    method.Statements.Add(new AsmStatement { Instruction = "call dword ptr [ecx]" });
                }
                else
                {
                    method.Statements.Add(new AsmStatement { Instruction = "call " + callLoc });
                }

                if (!calleeMethod.IsStatic)
                {
                    argSize += 4;
                }

                if (argSize > 0)
                {
                    method.Statements.Add(new AsmStatement { Instruction = "add esp," + argSize.ToString() });
                }

                if (calleeMethod.Parameters.Count != argTypes.Count)
                {
                    string message = string.Format(
                        System.Globalization.CultureInfo.InvariantCulture,
                        Properties.Resources.CodeGenerator_UnexpectedArgumentCount,
                        calleeMethod.Name,
                        calleeMethod.Parameters.Count,
                        argTypes.Count);
                    this.log.Write(new Message(
                        expression.Start.Path,
                        expression.Start.Line,
                        expression.Start.Column,
                        Severity.Error,
                        message));
                    valueType = null;
                    return false;
                }

                bool argsValid = true;
                for (int i = 0; i < calleeMethod.Parameters.Count; i++)
                {
                    if (!this.ValidateCanCast(expression, calleeMethod.Parameters[i].Type, argTypes[i]))
                    {
                        argsValid = false;
                    }
                }

                valueType = storageType;
                return argsValid;
            }

            ReferenceExpression refExpr = expression as ReferenceExpression;
            if (refExpr != null)
            {
                string location = null;
                TypeDefinition storageType = null;
                MethodInfo calleeMethod = null;
                if (!this.TryEmitReference(refExpr, context, scope, method, out location, out storageType, out calleeMethod))
                {
                    valueType = null;
                    return false;
                }

                if (storageType.IsFloatingPoint)
                {
                    if (storageType.Size == 8)
                    {
                        method.Statements.Add(new AsmStatement { Instruction = "fld qword ptr " + location });
                    }
                    else if (storageType.Size == 4)
                    {
                        method.Statements.Add(new AsmStatement { Instruction = "fld dword ptr " + location });
                    }
                    else
                    {
                        method.Statements.Add(new AsmStatement { Instruction = "fld tword ptr " + location });
                    }
                }
                else if (storageType.IsArray)
                {
                    if (storageType.ArrayElementCount > 0)
                    {
                        method.Statements.Add(new AsmStatement { Instruction = "lea eax," + location });
                        valueType = context.GetArrayType(storageType.InnerType, 0);
                        return true;
                    }
                    else
                    {
                        method.Statements.Add(new AsmStatement { Instruction = "mov eax," + location });
                    }
                }
                else if (storageType.Size <= 8 && !storageType.IsClass)
                {
                    switch (storageType.Size)
                    {
                        case 8:
                            method.Statements.Add(new AsmStatement { Instruction = "lea ecx, " + location });
                            method.Statements.Add(new AsmStatement { Instruction = "mov eax,[ecx]" });
                            method.Statements.Add(new AsmStatement { Instruction = "add ecx,4" });
                            method.Statements.Add(new AsmStatement { Instruction = "mov edx,[ecx]" });
                            break;
                        case 4:
                            method.Statements.Add(new AsmStatement { Instruction = "mov eax,dword ptr " + location });
                            break;
                        case 2:
                            method.Statements.Add(new AsmStatement { Instruction = "mov ax,word ptr " + location });
                            break;
                        case 1:
                            method.Statements.Add(new AsmStatement { Instruction = "mov al,byte ptr " + location });
                            break;
                    }
                }
                else if (storageType.IsClass)
                {
                    // construct a new copy on the stack.
                    method.Statements.Add(new AsmStatement { Instruction = string.Format("lea eax,{0}", location) });
                    method.Statements.Add(new AsmStatement { Instruction = string.Format("sub esp,{0}", storageType.Size) });
                    MethodInfo copyConstructor = storageType.GetCopyConstructor(context);
                    if (copyConstructor != null)
                    {
                        method.Module.AddProto(copyConstructor);
                        method.Statements.Add(new AsmStatement { Instruction = "lea ecx,[esp]" });
                        method.Statements.Add(new AsmStatement { Instruction = "push eax" });
                        method.Statements.Add(new AsmStatement { Instruction = "push ecx" });
                        method.Statements.Add(new AsmStatement { Instruction = "call " + copyConstructor.MangledName });
                        method.Statements.Add(new AsmStatement { Instruction = "add esp,8" });
                    }
                    else
                    {
                        // raw copy.
                        method.Statements.Add(new AsmStatement { Instruction = "mov edi,esp" });
                        method.Statements.Add(new AsmStatement { Instruction = "mov esi,eax" });
                        method.Statements.Add(new AsmStatement { Instruction = string.Format("mov ecx,{0}", storageType.Size) });
                        method.Statements.Add(new AsmStatement { Instruction = "cld" });
                        method.Statements.Add(new AsmStatement { Instruction = "rep movsb" });
                    }
                }

                valueType = storageType;
                return true;
            }

            SimpleExpression simpleExpr = expression as SimpleExpression;
            if (simpleExpr != null)
            {
                return this.TryEmitSimpleExpression(simpleExpr, context, scope, method, out valueType);
            }

            TermExpression termExpr = expression as TermExpression;
            if (termExpr != null)
            {
                return this.TryEmitTermExpression(termExpr, context, scope, method, out valueType);
            }

            RelationalExpression relExpr = expression as RelationalExpression;
            if (relExpr != null)
            {
                return this.TryEmitRelationExpresion(relExpr, context, scope, method, out valueType);
            }

            AddressExpression addrExpr = expression as AddressExpression;
            if (addrExpr != null)
            {
                return this.TryEmitAddressExpression(addrExpr, context, scope, method, out valueType);
            }

            NewExpression newExpr = expression as NewExpression;
            if (newExpr != null)
            {
                return this.TryEmitNewExpression(newExpr, context, scope, method, out valueType);
            }

            NotExpression notExpr = expression as NotExpression;
            if (notExpr != null)
            {
                return this.TryEmitNotExpression(notExpr, context, scope, method, out valueType);
            }

            NegativeExpression negExpr = expression as NegativeExpression;
            if (negExpr != null)
            {
                return this.TryEmitNegativeExpression(negExpr, context, scope, method, out valueType);
            }

            valueType = null;
            return false;
        }
Beispiel #9
0
 public NotExpression(Token start, Expression inner)
     : base(start)
 {
     this.Inner = inner;
 }
Beispiel #10
0
        private bool ValidateConditionType(Expression condition, TypeDefinition conditionType)
        {
            string message = Properties.Resources.CodeGenerator_BooleanConditionExpected;
            if (string.CompareOrdinal(conditionType.MangledName, "f") != 0)
            {
                this.log.Write(new Message(
                    condition.Start.Path,
                    condition.Start.Line,
                    condition.Start.Column,
                    Severity.Error,
                    message));
                return false;
            }

            return true;
        }
Beispiel #11
0
 public void AddArgument(Expression arg)
 {
     this.arguments.Add(arg);
 }
Beispiel #12
0
 public ArrayIndexReferenceExpression(Token start, ReferenceExpression inner, Expression index)
     : base(start)
 {
     this.Inner = inner;
     this.Index = index;
 }
Beispiel #13
0
 public AssignmentStatement(Token start, ReferenceExpression storage, Expression value)
     : base(start)
 {
     this.Value = value;
     this.Storage = storage;
 }
Beispiel #14
0
        private bool ParseExpression(TokenReader reader, out Expression result)
        {
            result = null;
            Token start = reader.Peek();
            Expression firstTerm = null;
            if (!this.ParseSimpleExpression(reader, out firstTerm))
            {
                return false;
            }

            Token tok = reader.Peek();
            if (tok.IsRelationalOperator())
            {
                reader.Read();
                Expression term = null;
                if (!this.ParseSimpleExpression(reader, out term))
                {
                    return false;
                }

                result = new RelationalExpression(start, firstTerm, ((KeywordToken)tok).Value, term);
            }
            else
            {
                result = firstTerm;
            }

            return true;
        }
Beispiel #15
0
 public ArrayTypeReference(Token start, Expression elementCount, TypeReference elementType)
     : base(start)
 {
     this.ElementCount = elementCount;
     this.ElementType = elementType;
 }
Beispiel #16
0
        private bool ParseFactorExpression(TokenReader reader, out Expression result)
        {
            Token tok = reader.Peek();
            if (tok.Is(Keyword.LeftParen))
            {
                reader.Read();
                if (!this.ParseExpression(reader, out result))
                {
                    return false;
                }

                if (!this.Expect(reader, Keyword.RightParen))
                {
                    return false;
                }

                return true;
            }

            if (tok.Is(Keyword.Not))
            {
                return this.ParseNotExpression(reader, out result);
            }

            if (tok.Is(Keyword.Minus))
            {
                return this.ParseNegativeExpression(reader, out result);
            }

            if (tok.Is(Keyword.New))
            {
                return this.ParseNewExpression(reader, out result);
            }

            if (tok.Is(Keyword.Nil))
            {
                reader.Read();
                result = new LiteralExpression(tok, null);
                return true;
            }

            if (tok.Is(Keyword.True))
            {
                reader.Read();
                result = new LiteralExpression(tok, true);
                return true;
            }

            if (tok.Is(Keyword.False))
            {
                reader.Read();
                result = new LiteralExpression(tok, false);
                return true;
            }

            LiteralToken literalTok = tok as LiteralToken;
            if (literalTok != null)
            {
                result = new LiteralExpression(tok, literalTok.Value);
                reader.Read();
                return true;
            }

            if (tok.Is(Keyword.Address))
            {
                return this.ParseAddressExpression(reader, out result);
            }

            if (tok is IdentifierToken || tok.Is(Keyword.Inherited))
            {
                ReferenceExpression refExpr = null;
                if (!this.ParseReferenceExpression(reader, out refExpr))
                {
                    result = null;
                    return false;
                }

                result = refExpr;
                return true;
            }

            string message = string.Format(
                System.Globalization.CultureInfo.CurrentCulture,
                Properties.Resources.Parser_Unexpected,
                tok != null ? tok.ToString() : Properties.Resources.Parser_EndOfFile);
            this.log.Write(new Message(reader.Path, reader.Line, reader.Column, Severity.Error, message));
            result = null;
            return false;
        }
Beispiel #17
0
 public DeleteStatement(Token start, Expression value)
     : base(start)
 {
     this.Value = value;
 }