コード例 #1
0
ファイル: CodeGenerator.cs プロジェクト: strunberg/TEA
        public bool CreateTypes(CompilerContext context, ProgramUnit programUnit)
        {
            bool failed = false;
            foreach (string uses in programUnit.Uses)
            {
                List<string> searchDirs = new List<string>();
                searchDirs.Add(System.IO.Path.GetDirectoryName(programUnit.Start.Path));
                searchDirs.AddRange(context.Includes);
                string headerPath = null;
                foreach (string dir in searchDirs)
                {
                    string includePath = System.IO.Path.Combine(
                        dir,
                        uses + ".th");
                    if (System.IO.File.Exists(includePath))
                    {
                        headerPath = includePath;
                        break;
                    }
                }

                if (headerPath != null && !context.AlreadyUsed(uses))
                {
                    context.AddAlreadyUsed(uses);
                    ProgramUnit usedProgramUnit = null;
                    using (TokenReader reader = new TokenReader(headerPath, this.log))
                    {
                        Parser includeParser = new Parser(this.log);
                        if (includeParser.TryParse(reader, out usedProgramUnit))
                        {
                            if (!this.CreateTypes(context, usedProgramUnit))
                            {
                                failed = true;
                            }
                        }
                        else
                        {
                            failed = true;
                        }
                    }
                }
            }

            context.ClearUses();
            foreach (string uses in programUnit.Uses)
            {
                context.AddUses(uses);
            }

            context.Namespace = programUnit.Namespace;
            foreach (TypeDeclaration typeDecl in programUnit.Types)
            {
                TypeDefinition typeDef = null;
                if (!context.TryDeclareType(typeDecl.Name, out typeDef))
                {
                    string message = string.Format(
                        Properties.Resources.CodeGenerator_TypeAlreadyDeclared,
                        typeDecl.Name);
                    log.Write(new Message(
                        typeDecl.Start.Path,
                        typeDecl.Start.Line,
                        typeDecl.Start.Column,
                        Severity.Error,
                        message));
                    failed = true;
                }

                ClassDeclaration classDecl = typeDecl as ClassDeclaration;
                if (classDecl != null)
                {
                    typeDef.IsClass = true;
                    typeDef.IsPublic = classDecl.IsPublic;
                    typeDef.IsStaticClass = classDecl.IsStatic;
                    if (classDecl.BaseType != null)
                    {
                        TypeDefinition baseType = null;
                        if (!context.TryFindTypeByName(classDecl.BaseType, out baseType))
                        {
                            string message = string.Format(
                                System.Globalization.CultureInfo.CurrentCulture,
                                Properties.Resources.CodeGenerator_UndefinedType,
                                classDecl.BaseType);
                            this.log.Write(new Message(
                                classDecl.Start.Path,
                                classDecl.Start.Line,
                                classDecl.Start.Column,
                                Severity.Error,
                                message));
                            failed = true;
                        }
                        else
                        {
                            if (!baseType.IsClass || baseType.IsStaticClass)
                            {
                                string message = string.Format(
                                    System.Globalization.CultureInfo.CurrentCulture,
                                    Properties.Resources.CodeGenerator_BaseTypeNotClass,
                                    baseType.FullName);
                                this.log.Write(new Message(
                                    classDecl.Start.Path,
                                    classDecl.Start.Line,
                                    classDecl.Start.Column,
                                    Severity.Error,
                                    message));
                                failed = true;
                            }
                            else
                            {
                                typeDef.BaseClass = baseType;
                            }
                        }
                    }

                    bool hasVirtualMethods = false;
                    foreach (MethodDeclaration meth in classDecl.PublicMethods)
                    {
                        MethodInfo methodInfo = null;
                        if (!this.TryCreateMethod(context, typeDef, meth, out methodInfo))
                        {
                            failed = true;
                            continue;
                        }

                        methodInfo.IsPublic = true;
                        typeDef.Methods.Add(methodInfo);
                        if (methodInfo.IsVirtual)
                        {
                            hasVirtualMethods = true;
                        }
                    }

                    foreach (MethodDeclaration meth in classDecl.ProtectedMethods)
                    {
                        MethodInfo methodInfo = null;
                        if (!this.TryCreateMethod(context, typeDef, meth, out methodInfo))
                        {
                            failed = true;
                            continue;
                        }

                        methodInfo.IsProtected = true;
                        typeDef.Methods.Add(methodInfo);
                        if (methodInfo.IsVirtual)
                        {
                            hasVirtualMethods = true;
                        }
                    }

                    foreach (MethodDeclaration meth in classDecl.PrivateMethods)
                    {
                        MethodInfo methodInfo = null;
                        if (!this.TryCreateMethod(context, typeDef, meth, out methodInfo))
                        {
                            failed = true;
                            continue;
                        }

                        methodInfo.IsProtected = true;
                        typeDef.Methods.Add(methodInfo);
                        if (methodInfo.IsVirtual)
                        {
                            hasVirtualMethods = true;
                        }
                    }

                    int size = 0;
                    if (typeDef.BaseClass != null)
                    {
                        size = typeDef.BaseClass.Size;
                    }

                    if (hasVirtualMethods)
                    {
                        FieldInfo vtblPtr = typeDef.GetVTablePointer();
                        if (vtblPtr == null)
                        {
                            vtblPtr = typeDef.AddVTablePointer(context, size);
                            size += vtblPtr.Type.Size;
                        }
                    }

                    if (classDecl.Fields != null)
                    {
                        foreach (var field in classDecl.Fields.Variables)
                        {
                            TypeDefinition fieldType = null;
                            if (!this.TryResolveTypeReference(context, field.Type, out fieldType))
                            {
                                failed = true;
                                continue;
                            }

                            foreach (string identifier in field.VariableNames)
                            {
                                FieldInfo fieldInfo = new FieldInfo();
                                fieldInfo.Name = identifier;
                                fieldInfo.Type = fieldType;
                                fieldInfo.IsStatic = classDecl.IsStatic;
                                if (!fieldInfo.IsStatic)
                                {
                                    fieldInfo.Offset = size;
                                    size += fieldType.Size;
                                }

                                typeDef.Fields.Add(fieldInfo);
                            }
                        }
                    }

                    typeDef.Size = size;
                }
            }

            return !failed;
        }
コード例 #2
0
ファイル: TypeDefinition.cs プロジェクト: strunberg/TEA
        public FieldInfo AddVTablePointer(CompilerContext context, int offset)
        {
            TypeDefinition ptrType = null;
            context.TryFindTypeByName("^", out ptrType);
            FieldInfo field = new FieldInfo
            {
                Name = VTablePointerFieldName,
                IsPublic = true,
                Offset = offset,
                Type = context.GetArrayType(ptrType, 0)
            };

            this.fields.Add(field);
            return field;
        }
コード例 #3
0
ファイル: CodeGenerator.cs プロジェクト: strunberg/TEA
        private bool TryResolveTypeReference(
            CompilerContext context, 
            TypeReference typeRef, 
            out TypeDefinition typeDef)
        {
            NamedTypeReference namedType = typeRef as NamedTypeReference;
            if (namedType != null)
            {
                if (!context.TryFindTypeByName(namedType.TypeName, out typeDef))
                {
                    string message = string.Format(
                        Properties.Resources.CodeGenerator_UndefinedType,
                        namedType.TypeName);
                    this.log.Write(new Message(
                        namedType.Start.Path,
                        namedType.Start.Line,
                        namedType.Start.Column,
                        Severity.Error,
                        message));
                    return false;
                }

                return true;
            }

            PointerTypeReference pointerType = typeRef as PointerTypeReference;
            if (pointerType != null)
            {
                TypeDefinition innerType = null;
                if (!this.TryResolveTypeReference(context, pointerType.ElementType, out innerType))
                {
                    typeDef = null;
                    return false;
                }

                typeDef = context.GetPointerType(innerType);
                return true;
            }

            ArrayTypeReference arrayType = typeRef as ArrayTypeReference;
            if (arrayType != null)
            {
                TypeDefinition innerType = null;
                if (!this.TryResolveTypeReference(context, arrayType.ElementType, out innerType))
                {
                    typeDef = null;
                    return false;
                }

                int elementCount = 0;
                if (arrayType.ElementCount != null)
                {
                    LiteralExpression litElementCount = arrayType.ElementCount as LiteralExpression;
                    if (litElementCount == null || !(litElementCount.Value is int))
                    {
                        log.Write(new Message(
                            arrayType.ElementCount.Start.Path,
                            arrayType.ElementCount.Start.Line,
                            arrayType.ElementCount.Start.Column,
                            Severity.Error,
                            Properties.Resources.CodeGenerator_ArrayTypeIntElementExpected));
                        typeDef = null;
                        return false;
                    }

                    elementCount = (int)(litElementCount.Value);
                }

                typeDef = context.GetArrayType(innerType, elementCount);
                return true;
            }

            typeDef = null;
            return false;
        }
コード例 #4
0
ファイル: CodeGenerator.cs プロジェクト: strunberg/TEA
        private bool TryFindSystemMemory(Token start, CompilerContext context, out TypeDefinition memoryType)
        {
            if (!context.TryFindTypeByName("System.Memory", out memoryType))
            {
                log.Write(new Message(
                    start.Path,
                    start.Line,
                    start.Column,
                    Severity.Error,
                    Properties.Resources.CodeGenerator_SystemMemoryNotDeclared));
                return false;
            }

            return true;
        }
コード例 #5
0
ファイル: CodeGenerator.cs プロジェクト: strunberg/TEA
        private bool TryEmitRelationExpresion(
            RelationalExpression relExpr, 
            CompilerContext context, 
            Scope scope, 
            MethodImpl method, 
            out TypeDefinition valueType)
        {
            context.TryFindTypeByName("boolean", out valueType);
            TypeDefinition rightSideType = null;
            if (!this.TryEmitExpression(relExpr.Right, context, scope, method, out rightSideType))
            {
                return false;
            }

            this.PushResult(method, rightSideType);
            TypeDefinition leftSideType = null;
            if (!this.TryEmitExpression(relExpr.Left, context, scope, method, out leftSideType))
            {
                return false;
            }

            if (rightSideType.IsFloatingPoint)
            {
                if (leftSideType.IsFloatingPoint)
                {
                    switch (rightSideType.Size)
                    {
                        case 4:
                            method.Statements.Add(new AsmStatement { Instruction = "fld dword ptr [esp]" });
                            break;
                        case 8:
                            method.Statements.Add(new AsmStatement { Instruction = "fld qword ptr [esp]" });
                            break;
                        default:
                            method.Statements.Add(new AsmStatement { Instruction = "fld tword ptr [esp]" });
                            break;
                    }

                    method.Statements.Add(new AsmStatement { Instruction = string.Format("add esp,{0}", rightSideType.Size) });
                    method.Statements.Add(new AsmStatement { Instruction = "fcompp" });
                    method.Statements.Add(new AsmStatement { Instruction = "fnstsw	ax" });
                    method.Statements.Add(new AsmStatement { Instruction = "sahf" });
                    switch (relExpr.Operator)
                    {
                        case Keyword.Equals:
                            {
                                method.Statements.Add(new AsmStatement { Instruction = "sete al" });
                            } break;
                        case Keyword.LessThan:
                            {
                                method.Statements.Add(new AsmStatement { Instruction = "seta al" });
                            } break;
                        case Keyword.LessThanOrEquals:
                            {
                                method.Statements.Add(new AsmStatement { Instruction = "setae al" });
                            } break;
                        case Keyword.GreaterThan:
                            {
                                method.Statements.Add(new AsmStatement { Instruction = "setb al" });
                            } break;
                        case Keyword.GreaterThanOrEquals:
                            {
                                method.Statements.Add(new AsmStatement { Instruction = "setbe al" });
                            } break;
                        case Keyword.NotEqual:
                            {
                                method.Statements.Add(new AsmStatement { Instruction = "setne al" });
                            } break;
                    }
                }
                else
                {
                    string message = string.Format(
                        System.Globalization.CultureInfo.InvariantCulture,
                        Properties.Resources.CodeGenerator_NoAutomaticConversion,
                        leftSideType.FullName,
                        rightSideType.FullName);
                    this.log.Write(new Message(
                        relExpr.Start.Path,
                        relExpr.Start.Line,
                        relExpr.Start.Column,
                        Severity.Error,
                        message));
                    return false;
                }
            }
            else if(leftSideType.IsFloatingPoint)
            {
                string message = string.Format(
                    System.Globalization.CultureInfo.InvariantCulture,
                    Properties.Resources.CodeGenerator_NoAutomaticConversion,
                    leftSideType.FullName,
                    rightSideType.FullName);
                this.log.Write(new Message(
                    relExpr.Start.Path,
                    relExpr.Start.Line,
                    relExpr.Start.Column,
                    Severity.Error,
                    message));
                return false;
            }
            else
            {
                if(leftSideType.Size <= 4 && rightSideType.Size <= 4)
                {
                    method.Statements.Add(new AsmStatement { Instruction = "pop ecx"});
                    method.Statements.Add(new AsmStatement { Instruction = "cmp eax,ecx"});
                    switch (relExpr.Operator)
                    {
                        case Keyword.Equals:
                            {
                                method.Statements.Add(new AsmStatement { Instruction = "sete al" });
                            } break;
                        case Keyword.LessThan:
                            {
                                method.Statements.Add(new AsmStatement { Instruction = "setl al" });
                            } break;
                        case Keyword.LessThanOrEquals:
                            {
                                method.Statements.Add(new AsmStatement { Instruction = "setle al" });
                            } break;
                        case Keyword.GreaterThan:
                            {
                                method.Statements.Add(new AsmStatement { Instruction = "setg al" });
                            } break;
                        case Keyword.GreaterThanOrEquals:
                            {
                                method.Statements.Add(new AsmStatement { Instruction = "setge al" });
                            } break;
                        case Keyword.NotEqual:
                            {
                                method.Statements.Add(new AsmStatement { Instruction = "setne al" });
                            } break;
                    }
                }
            }

            return true;
        }
コード例 #6
0
ファイル: CodeGenerator.cs プロジェクト: strunberg/TEA
        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;
        }
コード例 #7
0
ファイル: CodeGenerator.cs プロジェクト: strunberg/TEA
        private bool TryEmitLiteralExpression(
            LiteralExpression expression,
            CompilerContext context,
            Scope scope,
            MethodImpl method,
            out TypeDefinition valueType)
        {
            if (expression.Value == null)
            {
                method.Statements.Add(new AsmStatement { Instruction = "xor eax,eax" });
                return context.TryFindTypeByName("^", out valueType);
            }

            if (expression.Value is int)
            {
                if ((int)expression.Value == 0)
                {
                    method.Statements.Add(new AsmStatement { Instruction = "xor eax,eax" });
                }
                else
                {
                    method.Statements.Add(new AsmStatement { Instruction = string.Format("mov eax,{0}", expression.Value) });
                }

                return context.TryFindTypeByName("integer", out valueType);
            }

            if (expression.Value is char)
            {
                method.Statements.Add(new AsmStatement { Instruction = string.Format("mov eax,{0}", (int)expression.Value) });
                return context.TryFindTypeByName("character", out valueType);
            }

            if (expression.Value is string)
            {
                string label = method.Module.DefineLiteralString((string)expression.Value);
                method.Statements.Add(new AsmStatement { Instruction = string.Format("lea eax,[offset {0}]", label) });
                return context.TryFindTypeByName("#0character", out valueType);
            }

            if (expression.Value is decimal)
            {
                decimal exprValue = (decimal)expression.Value;
                if (exprValue == 0.0M)
                {
                    method.Statements.Add(new AsmStatement { Instruction = "fldz" });
                }
                else if (exprValue == 1.0M)
                {
                    method.Statements.Add(new AsmStatement { Instruction = "fld1" });
                }
                else
                {
                    string label = method.Module.DefineConstant((double)exprValue);
                    method.Statements.Add(new AsmStatement { Instruction = string.Format("fld qword ptr [{0}]", label) });
                }
                return context.TryFindTypeByName("double", out valueType);
            }

            if (expression.Value is bool)
            {
                bool boolVal = (bool)expression.Value;
                if (boolVal)
                {
                    method.Statements.Add(new AsmStatement { Instruction = "mov eax,1" });
                }
                else
                {
                    method.Statements.Add(new AsmStatement { Instruction = "xor eax,eax" });
                }

                return context.TryFindTypeByName("boolean", out valueType);
            }

            valueType = null;
            return false;
        }