Exemplo n.º 1
0
 public AddressExpression(Token start, ReferenceExpression inner)
     : base(start)
 {
     this.Inner = inner;
 }
Exemplo n.º 2
0
        private bool ParseReferenceExpression(TokenReader reader, out ReferenceExpression result)
        {
            ReferenceExpression inner = null;
            Token tok = reader.Peek();
            string identifier = null;
            if (tok.Is(Keyword.Inherited))
            {
                inner = new InheritedReferenceExpression(tok);
                reader.Read();
            }
            else
            {
                if (!this.ExpectIdentifier(reader, out identifier))
                {
                    result = null;
                    return false;
                }

                inner = new NamedReferenceExpression(tok, identifier);
            }

            tok = reader.Peek();
            while (true)
            {
                if (tok.Is(Keyword.LeftParen))
                {
                    reader.Read();
                    CallReferenceExpression callExpr = new CallReferenceExpression(tok, inner);
                    inner = callExpr;
                    tok = reader.Peek();
                    if (!tok.Is(Keyword.RightParen))
                    {
                        Expression arg = null;
                        if (!this.ParseExpression(reader, out arg))
                        {
                            result = null;
                            return false;
                        }

                        callExpr.AddArgument(arg);

                        tok = reader.Peek();
                        while (tok.Is(Keyword.Comma))
                        {
                            reader.Read();
                            if (!this.ParseExpression(reader, out arg))
                            {
                                result = null;
                                return false;
                            }

                            callExpr.AddArgument(arg);

                            tok = reader.Peek();
                        }
                    }

                    if (!this.Expect(reader, Keyword.RightParen))
                    {
                        result = null;
                        return false;
                    }
                }
                else if (tok.Is(Keyword.LeftBracket))
                {
                    reader.Read();
                    Expression index = null;
                    if (!this.ParseExpression(reader, out index))
                    {
                        result = null;
                        return false;
                    }

                    if (!this.Expect(reader, Keyword.RightBracket))
                    {
                        result = null;
                        return false;
                    }

                    inner = new ArrayIndexReferenceExpression(tok, inner, index);
                }
                else if (tok.Is(Keyword.Dot))
                {
                    reader.Read();
                    if (!this.ExpectIdentifier(reader, out identifier))
                    {
                        result = null;
                        return false;
                    }

                    inner = new MemberReferenceExpression(tok, inner, identifier);
                }
                else if (tok.Is(Keyword.Pointer))
                {
                    reader.Read();
                    inner = new DereferenceExpression(tok, inner);
                }
                else
                {
                    break;
                }

                tok = reader.Peek();
            }

            result = inner;
            return true;
        }
Exemplo n.º 3
0
        private bool TryEmitReference(
            ReferenceExpression referenceExpression,
            CompilerContext context,
            Scope scope,
            MethodImpl method,
            out string location,
            out TypeDefinition storageType,
            out MethodInfo calleeMethod)
        {
            calleeMethod = null;
            NamedReferenceExpression namedRef = referenceExpression as NamedReferenceExpression;
            if (namedRef != null)
            {
                SymbolEntry symbol = null;
                if (scope.TryLookup(namedRef.Identifier, out symbol))
                {
                    storageType = symbol.Type;
                    LocalVariable localVar = symbol as LocalVariable;
                    if (localVar != null)
                    {
                        location = string.Format("_{0}$[ebp]", localVar.Name);
                        return true;
                    }
                    else
                    {
                        ParameterVariable parVar = symbol as ParameterVariable;
                        if (parVar != null)
                        {
                            location = string.Format("_{0}$[ebp]", parVar.Name);
                            return true;
                        }
                    }
                }

                foreach (var field in method.Method.Type.Fields)
                {
                    if (string.CompareOrdinal(field.Name, namedRef.Identifier) == 0)
                    {
                        SymbolEntry symThis = null;
                        if(!scope.TryLookup("this", out symThis))
                        {
                            storageType = null;
                            location = null;
                            return false;
                        }

                        method.Statements.Add(
                            new AsmStatement
                            {
                                Instruction = "mov ecx,_this$[ebp]"
                            });
                        if (field.Offset > 0)
                        {
                            method.Statements.Add(
                                new AsmStatement { Instruction = "add ecx," + field.Offset });
                        }

                        storageType = field.Type;
                        location = "[ecx]";
                        return true;
                    }
                }

                foreach (var memberMethod in method.Method.Type.Methods)
                {
                    if (string.CompareOrdinal(memberMethod.Name, namedRef.Identifier) == 0)
                    {
                        method.Module.AddProto(memberMethod);
                        if (!memberMethod.IsStatic)
                        {
                            SymbolEntry symThis = null;
                            if (!scope.TryLookup("this", out symThis))
                            {
                                storageType = null;
                                location = null;
                                return false;
                            }

                            method.Statements.Add(
                                new AsmStatement
                                {
                                    Instruction = "mov ecx,_this$[ebp]"
                                });

                            method.Statements.Add(new AsmStatement { Instruction = "push ecx" });
                        }

                        if (memberMethod.IsVirtual)
                        {
                            location = "[ecx]";
                        }
                        else
                        {
                            location = memberMethod.MangledName;
                        }

                        storageType = memberMethod.ReturnType;
                        calleeMethod = memberMethod;
                        return true;
                    }
                }

                if (context.TryFindTypeByName(namedRef.Identifier, out storageType))
                {
                    location = null;
                    return true;
                }

                string message = string.Format(
                    Properties.Resources.CodeGenerator_UndeclaredIdentifier,
                    namedRef.Identifier);
                log.Write(new Message(
                    namedRef.Start.Path,
                    namedRef.Start.Line,
                    namedRef.Start.Column,
                    Severity.Error,
                    message));
            }

            MemberReferenceExpression memberRef = referenceExpression as MemberReferenceExpression;
            if (memberRef != null)
            {
                string innerLoc = null;
                TypeDefinition innerType = null;
                MethodInfo innerCalleeMethod = null;
                if (this.TryEmitReference(memberRef.Inner, context, scope, method, out innerLoc, out innerType, out innerCalleeMethod))
                {
                    foreach (var field in innerType.Fields)
                    {
                        if (string.CompareOrdinal(field.Name, memberRef.MemberName) == 0)
                        {
                            method.Statements.Add(
                                new AsmStatement
                                {
                                    Instruction = string.Format("lea ecx,{0}", innerLoc)
                                });
                            if (field.Offset > 0)
                            {
                                method.Statements.Add(
                                    new AsmStatement { Instruction = "add ecx," + field.Offset });
                            }

                            storageType = field.Type;
                            location = "[ecx]";
                            return true;
                        }
                    }

                    foreach (var memberMethod in innerType.Methods)
                    {
                        if (string.CompareOrdinal(memberMethod.Name, memberRef.MemberName) == 0)
                        {
                            method.Module.AddProto(memberMethod);
                            if (!memberMethod.IsStatic)
                            {
                                method.Statements.Add(new AsmStatement { Instruction = string.Format("lea eax,{0}", innerLoc) });
                                method.Statements.Add(new AsmStatement { Instruction = "push eax" });
                            }

                            if (memberMethod.IsVirtual && memberRef.UseVirtualDispatch)
                            {
                                location = "[eax]";
                            }
                            else
                            {
                                location = memberMethod.MangledName;
                            }

                            storageType = memberMethod.ReturnType;
                            calleeMethod = memberMethod;
                            return true;
                        }
                    }

                    string message = string.Format(
                        Properties.Resources.CodeGenerator_UndeclaredMember,
                        memberRef.MemberName,
                        innerType.FullName);
                    log.Write(new Message(
                        memberRef.Start.Path,
                        memberRef.Start.Line,
                        memberRef.Start.Column,
                        Severity.Error,
                        message));
                }
            }

            CallReferenceExpression callExpr = referenceExpression as CallReferenceExpression;
            if (callExpr != null)
            {
                location = null;
                return this.TryEmitExpression(callExpr, context, scope, method, out storageType);
            }

            ArrayIndexReferenceExpression arrayIndexExpr = referenceExpression as ArrayIndexReferenceExpression;
            if (arrayIndexExpr != null)
            {
                TypeDefinition indexType = null;
                if (!this.TryEmitExpression(
                    arrayIndexExpr.Index,
                    context,
                    scope,
                    method,
                    out indexType))
                {
                    location = null;
                    storageType = null;
                    return false;
                }

                if (indexType.IsFloatingPoint || indexType.IsArray || indexType.IsClass || indexType.IsPointer)
                {
                    this.log.Write(new Message(
                        arrayIndexExpr.Index.Start.Path,
                        arrayIndexExpr.Index.Start.Line,
                        arrayIndexExpr.Index.Start.Column,
                        Severity.Error,
                        Properties.Resources.CodeGenerator_ArrayIndexIntExpected));
                    location = null;
                    storageType = null;
                    return false;
                }

                method.Statements.Add(new AsmStatement { Instruction = "push eax" });
                string innerLoc = null;
                TypeDefinition innerType = null;
                MethodInfo arrayCalleeMethod = null;
                if (!this.TryEmitReference(
                    arrayIndexExpr.Inner,
                    context,
                    scope,
                    method,
                    out innerLoc,
                    out innerType,
                    out arrayCalleeMethod))
                {
                    location = null;
                    storageType = null;
                    return false;
                }

                if (!innerType.IsArray)
                {
                    log.Write(new Message(
                        arrayIndexExpr.Inner.Start.Path,
                        arrayIndexExpr.Inner.Start.Line,
                        arrayIndexExpr.Inner.Start.Column,
                        Severity.Error,
                        Properties.Resources.CodeGenerator_ArrayTypeExpected));
                    location = null;
                    storageType = null;
                    return false;
                }

                if (innerType.Size > 4)
                {
                    method.Statements.Add(new AsmStatement { Instruction = "lea ecx," + innerLoc });
                }
                else
                {
                    method.Statements.Add(new AsmStatement { Instruction = "mov ecx," + innerLoc });
                }

                method.Statements.Add(new AsmStatement { Instruction = "pop eax" });
                int elementSize = innerType.InnerType.Size;
                if(elementSize > 1)
                {
                    int shiftSize = 0;
                    switch(elementSize)
                    {
                        case 2:
                            shiftSize = 1;
                            break;
                        case 4:
                            shiftSize = 2;
                            break;
                        case 8:
                            shiftSize = 3;
                            break;
                        case 16:
                            shiftSize = 4;
                            break;
                        case 32:
                            shiftSize = 5;
                            break;
                        case 64:
                            shiftSize = 6;
                            break;
                        default:
                            method.Statements.Add(new AsmStatement { Instruction = string.Format("imul eax,{0}", elementSize) });
                            break;
                    }

                    if (shiftSize != 0)
                    {
                        method.Statements.Add(new AsmStatement { Instruction = string.Format("shl eax,{0}", shiftSize) });
                    }
                }

                method.Statements.Add(new AsmStatement { Instruction = "add ecx,eax" });
                location = "[ecx]";
                storageType = innerType.InnerType;
                return true;
            }

            DereferenceExpression derefExpr = referenceExpression as DereferenceExpression;
            if (derefExpr != null)
            {
                string innerLoc = null;
                TypeDefinition innerType = null;
                MethodInfo innerCall = null;
                if (!this.TryEmitReference(
                    derefExpr.Inner,
                    context,
                    scope,
                    method,
                    out innerLoc,
                    out innerType,
                    out innerCall))
                {
                    location = null;
                    storageType = null;
                    return false;
                }

                if (!innerType.IsPointer)
                {
                    log.Write(new Message(
                        derefExpr.Start.Path,
                        derefExpr.Start.Line,
                        derefExpr.Start.Column,
                        Severity.Error,
                        Properties.Resources.CodeGenerator_CannotDerefNonPointer));
                    location = null;
                    storageType = null;
                    return false;
                }

                method.Statements.Add(new AsmStatement { Instruction = "mov ecx," + innerLoc });
                location = "[ecx]";
                storageType = innerType.InnerType;
                return true;
            }

            InheritedReferenceExpression inhRefExpr = referenceExpression as InheritedReferenceExpression;
            if (inhRefExpr != null)
            {
                storageType = method.Method.Type.BaseClass;
                if (storageType == null)
                {
                    string message = string.Format(
                        System.Globalization.CultureInfo.CurrentCulture,
                        Properties.Resources.CodeGenerator_NoBaseTypeForInherited,
                        method.Method.Type.FullName);
                    this.log.Write(new Message(
                        inhRefExpr.Start.Path,
                        inhRefExpr.Start.Line,
                        inhRefExpr.Start.Column,
                        Severity.Error,
                        message));
                    location = null;
                    return false;
                }

                SymbolEntry thisSymbol = null;
                if (!scope.TryLookup("this", out thisSymbol))
                {
                    // reference a static on the base class.
                    location = null;
                }
                else
                {
                    location = "_this$[ebp]";
                }

                return true;
            }

            location = null;
            storageType = null;
            return false;
        }
Exemplo n.º 4
0
 public CallStatement(Token start, ReferenceExpression callExpression)
     : base(start)
 {
     this.Expression = callExpression;
 }
Exemplo n.º 5
0
 public MemberReferenceExpression(Token start, ReferenceExpression inner, string memberName)
     : base(start)
 {
     this.MemberName = memberName;
     this.Inner = inner;
 }
Exemplo n.º 6
0
 public ArrayIndexReferenceExpression(Token start, ReferenceExpression inner, Expression index)
     : base(start)
 {
     this.Inner = inner;
     this.Index = index;
 }
Exemplo n.º 7
0
 public AssignmentStatement(Token start, ReferenceExpression storage, Expression value)
     : base(start)
 {
     this.Value = value;
     this.Storage = storage;
 }