Пример #1
0
        public override Expression ResolveNamesAndCullUnusedCode(PastelCompiler compiler)
        {
            this.Expression = this.Expression.ResolveNamesAndCullUnusedCode(compiler);

            if (this.Expression is InlineConstant)
            {
                InlineConstant ic = (InlineConstant)this.Expression;
                if (this.FirstToken.Value == "!" && ic.Value is bool)
                {
                    return(new InlineConstant(PType.BOOL, this.FirstToken, !((bool)ic.Value)));
                }
                if (this.FirstToken.Value == "-")
                {
                    if (ic.Value is int)
                    {
                        return(new InlineConstant(PType.INT, this.FirstToken, -(int)ic.Value));
                    }
                    if (ic.Value is double)
                    {
                        return(new InlineConstant(PType.DOUBLE, this.FirstToken, -(double)ic.Value));
                    }
                }
                throw new ParserException(this.OpToken, "The op '" + this.OpToken.Value + "' is not valid on this type of expression.");
            }
            return(this);
        }
Пример #2
0
        public Executable ParseIfStatement(TokenStream tokens)
        {
            Token ifToken = tokens.PopExpected("if");

            tokens.PopExpected("(");
            Expression condition = this.ParseExpression(tokens);

            tokens.PopExpected(")");
            IList <Executable> ifCode   = this.ParseCodeBlock(tokens, false);
            Token elseToken             = null;
            IList <Executable> elseCode = EMPTY_CODE_BLOCK;

            if (tokens.IsNext("else"))
            {
                elseToken = tokens.Pop();
                elseCode  = this.ParseCodeBlock(tokens, false);
            }

            if (condition is InlineConstant)
            {
                InlineConstant ic = (InlineConstant)condition;
                if (ic.Value is bool)
                {
                    return(new ExecutableBatch(ifToken, (bool)ic.Value ? ifCode : elseCode));
                }
            }

            return(new IfStatement(ifToken, condition, ifCode, elseToken, elseCode));
        }
Пример #3
0
        private IfStatement BuildIfStatement(int id, string op, Executable[] trueCode, Executable[] falseCode)
        {
            Pastel.Token equalsToken = Pastel.Token.CreateDummyToken(op);
            Variable     variable    = new Variable(Pastel.Token.CreateDummyToken(this.ConditionVariableName));

            variable.ApplyPrefix = false;
            Expression condition = new OpChain(new Expression[] { variable, InlineConstant.Of(id) }, new Pastel.Token[] { equalsToken });

            return(new IfStatement(
                       Pastel.Token.CreateDummyToken("if"),
                       condition,
                       TrimBreak(trueCode),
                       Pastel.Token.CreateDummyToken("else"),
                       TrimBreak(falseCode)));
        }
Пример #4
0
        public static PythonFakeSwitchStatement Build(SwitchStatement switchStatement, int switchId, string functionName)
        {
            ICompilationEntity owner = switchStatement.Condition.Owner;
            Dictionary <InlineConstant, int> expressionToId = new Dictionary <InlineConstant, int>();
            Dictionary <int, Executable[]>   codeById       = new Dictionary <int, Executable[]>();
            int?nullableDefaultId = null;

            Executable[] defaultCode = null;
            for (int i = 0; i < switchStatement.Chunks.Length; ++i)
            {
                SwitchStatement.SwitchChunk chunk = switchStatement.Chunks[i];
                int          currentId            = i;
                Expression[] cases = chunk.Cases;
                for (int j = 0; j < cases.Length; ++j)
                {
                    InlineConstant caze = (InlineConstant)cases[j];
                    if (caze == null)
                    {
                        nullableDefaultId = currentId;
                        defaultCode       = chunk.Code;
                    }
                    else
                    {
                        expressionToId[caze] = currentId;
                    }
                }

                codeById[currentId] = chunk.Code;
            }

            int defaultId;

            if (nullableDefaultId != null)
            {
                defaultId = nullableDefaultId.Value;
                if (!codeById.ContainsKey(defaultId))
                {
                    codeById[defaultId] = defaultCode;
                }
            }
            else
            {
                defaultId           = codeById.Count;
                codeById[defaultId] = new Executable[0];
            }

            return(new PythonFakeSwitchStatement(functionName, switchId, defaultId, expressionToId, codeById, owner));
        }
Пример #5
0
        public override Expression ResolveNamesAndCullUnusedCode(PastelCompiler compiler)
        {
            string name = this.Name;

            InlineConstant constantValue = compiler.GetConstantDefinition(name);

            if (constantValue != null)
            {
                return(constantValue.CloneWithNewToken(this.FirstToken));
            }

            FunctionDefinition functionDefinition = compiler.GetFunctionDefinitionAndMaybeQueueForResolution(name);

            if (functionDefinition != null)
            {
                return(new FunctionReference(this.FirstToken, functionDefinition));
            }

            return(this);
        }
Пример #6
0
        public override void TranslateArrayNew(TranspilerContext sb, PType arrayType, Expression lengthExpression)
        {
            if (lengthExpression is InlineConstant)
            {
                InlineConstant ic     = (InlineConstant)lengthExpression;
                int            length = (int)ic.Value;
                switch (length)
                {
                case 0: sb.Append("[]"); return;

                case 1: sb.Append("[None]"); return;

                case 2: sb.Append("[None, None]"); return;

                default: break;
                }
            }
            sb.Append("(TranslationHelper_NoneListOfOne * ");
            this.TranslateExpression(sb, lengthExpression);
            sb.Append(")");
        }
Пример #7
0
        public override void TranslateArrayNew(StringBuilder sb, PType arrayType, Expression lengthExpression)
        {
            if (lengthExpression is InlineConstant)
            {
                InlineConstant ic     = (InlineConstant)lengthExpression;
                int            length = (int)ic.Value;
                switch (length)
                {
                case 0: sb.Append("[]"); return;

                case 1: sb.Append("[None]"); return;

                case 2: sb.Append("[None, None]"); return;

                default: break;
                }
            }
            TODO.UseGlobalListOfOneNoneToPreventFrequentReallocation();
            sb.Append("([None] * ");
            this.TranslateExpression(sb, lengthExpression);
            sb.Append(")");
        }
Пример #8
0
        public void TranslateExpression(StringBuilder sb, Expression expression)
        {
            string typeName = expression.GetType().Name;

            switch (typeName)
            {
            case "CastExpression": this.TranslateCast(sb, ((CastExpression)expression).Type, ((CastExpression)expression).Expression); break;

            case "FunctionReference": this.TranslateFunctionReference(sb, (FunctionReference)expression); break;

            case "NativeFunctionInvocation": this.TranslateNativeFunctionInvocation(sb, (NativeFunctionInvocation)expression); break;

            case "OpChain": this.TranslateOpChain(sb, (OpChain)expression); break;

            case "LibraryNativeFunctionInvocation": this.TranslateLibraryNativeFunctionInvocation(sb, (LibraryNativeFunctionInvocation)expression); break;

            case "InlineIncrement":
                InlineIncrement ii = (InlineIncrement)expression;
                this.TranslateInlineIncrement(sb, ii.Expression, ii.IsPrefix, ii.IncrementToken.Value == "++");
                break;

            case "FunctionInvocation":
                FunctionInvocation funcInvocation = (FunctionInvocation)expression;
                bool specifyInterpreterScope      = false;
                if (funcInvocation.FirstToken.FileName.StartsWith("LIB:") &&
                    funcInvocation.Root is FunctionReference)
                {
                    FunctionDefinition funcDef = ((FunctionReference)funcInvocation.Root).Function;
                    if (!funcDef.NameToken.FileName.StartsWith("LIB:"))
                    {
                        specifyInterpreterScope = true;
                    }
                }

                if (specifyInterpreterScope)
                {
                    this.TranslateFunctionInvocationInterpreterScoped(sb, (FunctionReference)funcInvocation.Root, funcInvocation.Args);
                }
                else
                {
                    this.TranslateFunctionInvocationLocallyScoped(sb, (FunctionReference)funcInvocation.Root, funcInvocation.Args);
                }
                break;

            case "Variable":
                Variable v         = (Variable)expression;
                string   name      = v.Name;
                char     firstChar = name[0];
                if (firstChar >= 'A' && firstChar <= 'Z' && name.Contains('_') && name.ToUpper() == name)
                {
                    this.TranslateGlobalVariable(sb, v);
                }
                else
                {
                    this.TranslateVariable(sb, v);
                }
                break;

            case "ConstructorInvocation":
                ConstructorInvocation constructor = (ConstructorInvocation)expression;
                string rootType = constructor.Type.RootValue;
                switch (rootType)
                {
                case "Array":
                    if (constructor.Type.Generics.Length != 1)
                    {
                        throw new Pastel.ParserException(constructor.Type.FirstToken, "Array constructor requires exactly 1 generic type.");
                    }
                    this.TranslateArrayNew(sb, constructor.Type.Generics[0], constructor.Args[0]);
                    break;

                case "List":
                    if (constructor.Type.Generics.Length != 1)
                    {
                        throw new Pastel.ParserException(constructor.Type.FirstToken, "List constructor requires exactly 1 generic type.");
                    }
                    this.TranslateListNew(sb, constructor.Type.Generics[0]);
                    break;

                case "Dictionary":
                    if (constructor.Type.Generics.Length != 2)
                    {
                        throw new Pastel.ParserException(constructor.Type.FirstToken, "Dictionary constructor requires exactly 2 generic types.");
                    }
                    PType dictionaryKeyType   = constructor.Type.Generics[0];
                    PType dictionaryValueType = constructor.Type.Generics[1];
                    this.TranslateDictionaryNew(sb, dictionaryKeyType, dictionaryValueType);
                    break;

                default:
                    // TODO: throw an exception (in the parser) if generics exist.
                    this.TranslateConstructorInvocation(sb, constructor);
                    break;
                }
                break;

            case "DotField":
                DotField         df        = (DotField)expression;
                StructDefinition structDef = df.StructType;
                if (structDef == null)
                {
                    throw new InvalidOperationException();                        // should have been thrown by the compiler
                }
                string fieldName  = df.FieldName.Value;
                int    fieldIndex = structDef.ArgIndexByName[fieldName];
                this.TranslateStructFieldDereference(sb, df.Root, structDef, fieldName, fieldIndex);
                break;

            case "InlineConstant":
                InlineConstant ic = (InlineConstant)expression;
                switch (ic.ResolvedType.RootValue)
                {
                case "bool": this.TranslateBooleanConstant(sb, (bool)ic.Value); break;

                case "char": this.TranslateCharConstant(sb, ((string)ic.Value)[0]); break;

                case "double": this.TranslateFloatConstant(sb, (double)ic.Value); break;

                case "int": this.TranslateIntegerConstant(sb, (int)ic.Value); break;

                case "null": this.TranslateNullConstant(sb); break;

                case "string": this.TranslateStringConstant(sb, (string)ic.Value); break;

                default: throw new NotImplementedException();
                }
                break;

            case "UnaryOp":
                UnaryOp uo = (UnaryOp)expression;
                if (uo.OpToken.Value == "-")
                {
                    this.TranslateNegative(sb, uo);
                }
                else
                {
                    this.TranslateBooleanNot(sb, uo);
                }
                break;

            case "ForcedParenthesis":
                sb.Append('(');
                this.TranslateExpression(sb, ((ForcedParenthesis)expression).Expression);
                sb.Append(')');
                break;

            default: throw new NotImplementedException(typeName);
            }
        }
Пример #9
0
        public ClassDefinition ParseClassDefinition(TokenStream tokens)
        {
            Token           classToken    = tokens.PopExpected("class");
            Token           nameToken     = tokens.PopIdentifier();
            ClassDefinition cd            = new ClassDefinition(this.context, classToken, nameToken);
            List <Token>    inheritTokens = new List <Token>();

            if (tokens.PopIfPresent(":"))
            {
                while (!tokens.IsNext("{"))
                {
                    if (inheritTokens.Count > 0)
                    {
                        tokens.PopExpected(",");
                    }
                    inheritTokens.Add(tokens.PopIdentifier());
                }
            }
            cd.InheritTokens = inheritTokens.ToArray();
            tokens.PopExpected("{");

            Dictionary <string, ICompilationEntity> members = new Dictionary <string, ICompilationEntity>();

            while (!tokens.PopIfPresent("}"))
            {
                string next = tokens.PeekValue();
                if (next == "constructor")
                {
                    if (cd.Constructor != null)
                    {
                        throw new ParserException(tokens.Peek(), "Only one constructor is permitted per class.");
                    }

                    Token constructorToken = tokens.PopExpected("constructor");
                    tokens.PopExpected("(");
                    List <PType> argTypes = new List <PType>();
                    List <Token> argNames = new List <Token>();
                    while (!tokens.PopIfPresent(")"))
                    {
                        if (argTypes.Count > 0)
                        {
                            tokens.PopExpected(",");
                        }
                        argTypes.Add(PType.Parse(tokens));
                        argNames.Add(tokens.PopIdentifier());
                    }
                    cd.Constructor        = new ConstructorDefinition(this.context, constructorToken, argTypes, argNames, cd);
                    this.currentCodeOwner = cd.Constructor;
                    cd.Constructor.Code   = this.ParseCodeBlock(tokens, true).ToArray();
                }
                else
                {
                    ICompilationEntity entity;
                    string             entityName;
                    PType memberType = PType.TryParse(tokens);
                    Token memberName = tokens.PopIdentifier();
                    bool  isMethod   = tokens.IsNext("(");
                    if (isMethod)
                    {
                        tokens.PopExpected("(");
                        List <PType> argTypes = new List <PType>();
                        List <Token> argNames = new List <Token>();
                        while (!tokens.PopIfPresent(")"))
                        {
                            if (argTypes.Count > 0)
                            {
                                tokens.PopExpected(",");
                            }
                            argTypes.Add(PType.Parse(tokens));
                            argNames.Add(tokens.PopIdentifier());
                        }
                        FunctionDefinition fd = new FunctionDefinition(memberName, memberType, argTypes, argNames, this.context, cd);
                        this.currentCodeOwner = fd;
                        List <Executable> code = this.ParseCodeBlock(tokens, true);
                        fd.Code    = code.ToArray();
                        entity     = fd;
                        entityName = fd.Name;
                    }
                    else
                    {
                        FieldDefinition fd = new FieldDefinition(this.context, memberType, memberName, cd);
                        this.currentCodeOwner = fd;
                        Expression initialValue = null;
                        if (tokens.PopIfPresent("="))
                        {
                            initialValue = this.ParseExpression(tokens);
                        }
                        else
                        {
                            if (memberType.IsNullable)
                            {
                                initialValue = new InlineConstant(memberType, memberName, null, cd);
                            }
                            else
                            {
                                switch (memberType.RootValue)
                                {
                                case "double": initialValue = new InlineConstant(memberType, memberName, 0.0, cd); break;

                                case "int": initialValue = new InlineConstant(memberType, memberName, 0, cd); break;

                                case "string": initialValue = new InlineConstant(memberType, memberName, null, cd); break;

                                default: throw new NotImplementedException();
                                }
                            }
                        }
                        tokens.PopExpected(";");
                        fd.Value   = initialValue;
                        entity     = fd;
                        entityName = fd.NameToken.Value;
                    }

                    if (members.ContainsKey(entityName))
                    {
                        throw new ParserException(memberName,
                                                  "There are conflicting members in the class '" + cd.NameToken.Value + "' for the name '" + entityName + "'.");
                    }

                    members[entityName] = entity;
                }
            }

            cd.AddMembers(members);

            return(cd);
        }
Пример #10
0
        public void TranslateExpression(TranspilerContext sb, Expression expression)
        {
            string typeName = expression.GetType().Name;

            switch (typeName)
            {
            case "CastExpression": this.TranslateCast(sb, ((CastExpression)expression).Type, ((CastExpression)expression).Expression); break;

            case "FunctionReference": this.TranslateFunctionReference(sb, (FunctionReference)expression); break;

            case "FunctionPointerInvocation": this.TranslateFunctionPointerInvocation(sb, (FunctionPointerInvocation)expression); break;

            case "CoreFunctionInvocation": this.TranslateCoreFunctionInvocation(sb, (CoreFunctionInvocation)expression); break;

            case "OpChain":
                OpChain oc = (OpChain)expression;
                if (oc.IsStringConcatenation)
                {
                    this.TranslateStringConcatenation(sb, oc.Expressions);
                }
                else
                {
                    this.TranslateOpChain(sb, oc);
                }
                break;

            case "ExtensibleFunctionInvocation":
                this.TranslateExtensibleFunctionInvocation(
                    sb,
                    (ExtensibleFunctionInvocation)expression);
                break;

            case "InlineIncrement":
                InlineIncrement ii = (InlineIncrement)expression;
                this.TranslateInlineIncrement(sb, ii.Expression, ii.IsPrefix, ii.IncrementToken.Value == "++");
                break;

            case "FunctionInvocation":
                FunctionInvocation funcInvocation = (FunctionInvocation)expression;
                string             prefix         = null;
                FunctionDefinition funcDef        = ((FunctionReference)funcInvocation.Root).Function;
                PastelContext      targetContext  = funcDef.Context;
                PastelContext      callerContext  = funcInvocation.Owner.Context;
                if (targetContext != callerContext)
                {
                    prefix = callerContext.GetDependencyExportPrefix(targetContext);
                }

                if (prefix != null)
                {
                    this.TranslateFunctionInvocationWithPrefix(sb, prefix, (FunctionReference)funcInvocation.Root, funcInvocation.Args);
                }
                else
                {
                    this.TranslateFunctionInvocation(sb, (FunctionReference)funcInvocation.Root, funcInvocation.Args);
                }
                break;

            case "Variable":
                Variable v = (Variable)expression;
                this.TranslateVariable(sb, v);
                break;

            case "ConstructorInvocation":
                ConstructorInvocation constructor = (ConstructorInvocation)expression;
                string rootType = constructor.Type.RootValue;
                switch (rootType)
                {
                case "Array":
                    if (constructor.Type.Generics.Length != 1)
                    {
                        throw new Pastel.ParserException(constructor.Type.FirstToken, "Array constructor requires exactly 1 generic type.");
                    }
                    this.TranslateArrayNew(sb, constructor.Type.Generics[0], constructor.Args[0]);
                    break;

                case "List":
                    if (constructor.Type.Generics.Length != 1)
                    {
                        throw new Pastel.ParserException(constructor.Type.FirstToken, "List constructor requires exactly 1 generic type.");
                    }
                    this.TranslateListNew(sb, constructor.Type.Generics[0]);
                    break;

                case "Dictionary":
                    if (constructor.Type.Generics.Length != 2)
                    {
                        throw new Pastel.ParserException(constructor.Type.FirstToken, "Dictionary constructor requires exactly 2 generic types.");
                    }
                    PType dictionaryKeyType   = constructor.Type.Generics[0];
                    PType dictionaryValueType = constructor.Type.Generics[1];
                    this.TranslateDictionaryNew(sb, dictionaryKeyType, dictionaryValueType);
                    break;

                case "StringBuilder":
                    if (constructor.Type.Generics.Length != 0)
                    {
                        throw new ParserException(constructor.Type.FirstToken, "StringBuilder constructor does not have any generics.");
                    }
                    this.TranslateStringBuilderNew(sb);
                    break;

                default:
                    // TODO: throw an exception (in the parser) if generics exist.
                    this.TranslateConstructorInvocation(sb, constructor);
                    break;
                }
                break;

            case "DotField":
                DotField         df        = (DotField)expression;
                StructDefinition structDef = df.StructType;
                ClassDefinition  classDef  = df.ClassType;
                string           fieldName = df.FieldName.Value;
                if (classDef != null)
                {
                    this.TranslateInstanceFieldDereference(sb, df.Root, classDef, fieldName);
                }
                else if (structDef != null)
                {
                    int fieldIndex = structDef.FlatFieldIndexByName[fieldName];
                    this.TranslateStructFieldDereference(sb, df.Root, structDef, fieldName, fieldIndex);
                }
                else
                {
                    throw new InvalidOperationException();     // should have been thrown by the compiler
                }
                break;

            case "InlineConstant":
                InlineConstant ic = (InlineConstant)expression;
                switch (ic.ResolvedType.RootValue)
                {
                case "bool": this.TranslateBooleanConstant(sb, (bool)ic.Value); break;

                case "char": this.TranslateCharConstant(sb, ((string)ic.Value)[0]); break;

                case "double": this.TranslateFloatConstant(sb, (double)ic.Value); break;

                case "int": this.TranslateIntegerConstant(sb, (int)ic.Value); break;

                case "null": this.TranslateNullConstant(sb); break;

                case "string": this.TranslateStringConstant(sb, (string)ic.Value); break;

                default: throw new NotImplementedException();
                }
                break;

            case "ThisExpression":
                this.TranslateThis(sb, (ThisExpression)expression);
                break;

            case "UnaryOp":
                UnaryOp uo = (UnaryOp)expression;
                if (uo.OpToken.Value == "-")
                {
                    this.TranslateNegative(sb, uo);
                }
                else
                {
                    this.TranslateBooleanNot(sb, uo);
                }
                break;

            case "ForcedParenthesis":
                sb.Append('(');
                this.TranslateExpression(sb, ((ForcedParenthesis)expression).Expression);
                sb.Append(')');
                break;

            default: throw new NotImplementedException(typeName);
            }
        }