示例#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
        internal Expression MaybeImmediatelyResolve(PastelParser parser)
        {
            if (this.Root is CompileTimeFunctionReference)
            {
                CompileTimeFunctionReference constFunc = (CompileTimeFunctionReference)this.Root;
                InlineConstant argName = (InlineConstant)this.Args[0];
                switch (constFunc.NameToken.Value)
                {
                case "ext_boolean":
                    return(new InlineConstant(
                               PType.BOOL,
                               this.FirstToken,
                               parser.GetParseTimeBooleanConstant(argName.Value.ToString())));

                case "ext_integer":
                    return(new InlineConstant(
                               PType.INT,
                               this.FirstToken,
                               parser.GetParseTimeIntegerConstant(argName.Value.ToString())));

                default:
                    return(this);
                }
            }
            return(this);
        }
示例#3
0
        internal override InlineConstant DoConstantResolution(HashSet <string> cycleDetection, PastelCompiler compiler)
        {
            for (int i = 0; i < this.Expressions.Length; ++i)
            {
                this.Expressions[i] = this.Expressions[i].DoConstantResolution(cycleDetection, compiler);
            }

            InlineConstant current = (InlineConstant)this.Expressions[0];

            for (int i = 1; i < this.Expressions.Length; ++i)
            {
                InlineConstant next   = (InlineConstant)this.Expressions[i];
                string         lookup = current.Type.RootValue + this.Ops[i - 1].Value + next.Type.RootValue;
                switch (lookup)
                {
                case "int+int":
                    current = new InlineConstant(PType.INT, current.FirstToken, (int)current.Value + (int)next.Value);
                    break;

                case "int-int":
                    current = new InlineConstant(PType.INT, current.FirstToken, (int)current.Value - (int)next.Value);
                    break;

                case "int*int":
                    current = new InlineConstant(PType.INT, current.FirstToken, (int)current.Value * (int)next.Value);
                    break;

                default:
                    throw new NotImplementedException();
                }
            }
            return(current);
        }
示例#4
0
        public EnumDefinition(Token enumToken, Token nameToken, IList <Token> valueTokens, IList <Expression> valueExpressions)
        {
            this.FirstToken   = enumToken;
            this.NameToken    = nameToken;
            this.ValueTokens  = valueTokens.ToArray();
            this.ValuesByName = new Dictionary <string, Expression>();
            int           length       = this.ValueTokens.Length;
            int           highestValue = 0;
            bool          highestSet   = false;
            List <string> autoAssignMe = new List <string>();

            for (int i = 0; i < length; ++i)
            {
                string name = this.ValueTokens[i].Value;
                if (this.ValuesByName.ContainsKey(name))
                {
                    throw new ParserException(this.FirstToken, "The enum '" + this.NameToken.Value + "' has multiple definitions of '" + name + "'");
                }
                Expression expression = valueExpressions[i];
                if (expression == null)
                {
                    autoAssignMe.Add(name);
                }
                else
                {
                    this.ValuesByName[name] = expression;

                    if (expression is InlineConstant)
                    {
                        InlineConstant ic = (InlineConstant)expression;
                        if (ic.Value is int)
                        {
                            if (!highestSet || (int)ic.Value > highestValue)
                            {
                                highestValue = (int)ic.Value;
                                highestSet   = true;
                            }
                        }
                        else
                        {
                            throw new ParserException(expression.FirstToken, "Only integers are allowed as enum values.");
                        }
                    }
                    else
                    {
                        this.UnresolvedValues.Add(name);
                    }
                }
            }

            // anything that doesn't have a value assigned to it, auto-assign incrementally from the highest value provided.
            foreach (string name in autoAssignMe)
            {
                this.ValuesByName[name] = new InlineConstant(PType.INT, this.FirstToken, highestValue++);
            }
        }
示例#5
0
        internal override Expression ResolveType(VariableScope varScope, PastelCompiler compiler)
        {
            this.Root  = this.Root.ResolveType(varScope, compiler);
            this.Index = this.Index.ResolveType(varScope, compiler);

            PType rootType  = this.Root.ResolvedType;
            PType indexType = this.Index.ResolvedType;

            bool badIndex = false;

            if (rootType.RootValue == "List" || rootType.RootValue == "Array")
            {
                badIndex          = !indexType.IsIdentical(PType.INT);
                this.ResolvedType = rootType.Generics[0];
            }
            else if (rootType.RootValue == "Dictionary")
            {
                badIndex          = !indexType.IsIdentical(rootType.Generics[0]);
                this.ResolvedType = rootType.Generics[1];
            }
            else if (rootType.RootValue == "string")
            {
                badIndex          = !indexType.IsIdentical(PType.INT);
                this.ResolvedType = PType.CHAR;
                if (this.Root is InlineConstant && this.Index is InlineConstant)
                {
                    string         c        = ((string)((InlineConstant)this.Root).Value)[(int)((InlineConstant)this.Index).Value].ToString();
                    InlineConstant newValue = new InlineConstant(PType.CHAR, this.FirstToken, c);
                    newValue.ResolveType(varScope, compiler);
                    return(newValue);
                }
            }
            else
            {
                badIndex = true;
            }

            if (badIndex)
            {
                throw new ParserException(this.BracketToken, "Cannot index into a " + rootType + " with a " + indexType + ".");
            }

            return(this);
        }
示例#6
0
        public override Expression ResolveNamesAndCullUnusedCode(PastelCompiler compiler)
        {
            string name = this.Name;

            InlineConstant constantValue = compiler.GetConstantDefinition(name);

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

            if (name == "Core")
            {
                return(new CoreNamespaceReference(this.FirstToken, this.Owner));
            }

            if (name == "Extension")
            {
                return(new ExtensibleNamespaceReference(this.FirstToken, this.Owner));
            }

            FunctionDefinition functionDefinition = compiler.GetFunctionDefinition(name);

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

            EnumDefinition enumDefinition = compiler.GetEnumDefinition(name);

            if (enumDefinition != null)
            {
                return(new EnumReference(this.FirstToken, enumDefinition, this.Owner));
            }

            if (compiler.IncludedScopeNamespacesToIndex.ContainsKey(name))
            {
                int            index           = compiler.IncludedScopeNamespacesToIndex[name];
                PastelCompiler referencedScope = compiler.IncludedScopes[index];
                return(new DependencyNamespaceReference(this.FirstToken, referencedScope, this.Owner));
            }

            return(this);
        }
示例#7
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);
        }
示例#8
0
        public override Expression ResolveNamesAndCullUnusedCode(PastelCompiler compiler)
        {
            this.Root = this.Root.ResolveNamesAndCullUnusedCode(compiler);

            Variable varRoot = this.Root as Variable;

            if (varRoot != null)
            {
                string rootName = varRoot.Name;
                if (rootName == "Core")
                {
                    NativeFunction nativeFunction = this.GetNativeCoreFunction(this.FieldName.Value);
                    switch (nativeFunction)
                    {
                    case NativeFunction.FLOAT_BUFFER_16:
                    case NativeFunction.INT_BUFFER_16:
                    case NativeFunction.STRING_BUFFER_16:
                        return(new NativeFunctionInvocation(this.FirstToken, nativeFunction, new Expression[0]));

                    default:
                        return(new NativeFunctionReference(this.FirstToken, nativeFunction));
                    }
                }
                EnumDefinition enumDef = compiler.GetEnumDefinition(rootName);
                if (enumDef != null)
                {
                    InlineConstant enumValue = enumDef.GetValue(this.FieldName);
                    return(enumValue.CloneWithNewToken(this.FirstToken));
                }
            }
            else if (this.Root is EnumReference)
            {
                EnumDefinition enumDef   = ((EnumReference)this.Root).EnumDef;
                InlineConstant enumValue = enumDef.GetValue(this.FieldName);
                return(enumValue);
            }

            return(this);
        }
示例#9
0
        internal override Executable ResolveWithTypeContext(PastelCompiler compiler)
        {
            this.Condition = this.Condition.ResolveWithTypeContext(compiler);
            HashSet <int> values = new HashSet <int>();

            for (int i = 0; i < this.Chunks.Length; ++i)
            {
                SwitchChunk chunk = this.Chunks[i];
                for (int j = 0; j < chunk.Cases.Length; ++j)
                {
                    if (chunk.Cases[j] != null)
                    {
                        chunk.Cases[j] = chunk.Cases[j].ResolveWithTypeContext(compiler);
                        InlineConstant ic = chunk.Cases[j] as InlineConstant;
                        if (ic == null)
                        {
                            throw new ParserException(chunk.Cases[j].FirstToken, "Only constants may be used as switch cases.");
                        }
                        int value;
                        if (ic.ResolvedType.RootValue == "char")
                        {
                            value = (char)ic.Value;
                        }
                        else
                        {
                            value = (int)ic.Value;
                        }
                        if (values.Contains(value))
                        {
                            throw new ParserException(chunk.Cases[j].FirstToken, "This cases appears multiple times.");
                        }
                        values.Add(value);
                    }
                }
                Executable.ResolveWithTypeContext(compiler, chunk.Code);
            }
            return(this);
        }
示例#10
0
        internal void DoConstantResolutions(HashSet <string> cycleDetection, PastelCompiler compiler)
        {
            string prefix = this.NameToken.Value + ".";

            foreach (string name in this.UnresolvedValues)
            {
                string cycleKey = prefix + name;
                if (cycleDetection.Contains(cycleKey))
                {
                    throw new ParserException(this.FirstToken, "This enum has a cycle in its value declarations in '" + name + "'");
                }
                cycleDetection.Add(cycleKey);

                InlineConstant ic = this.ValuesByName[cycleKey].DoConstantResolution(cycleDetection, compiler);
                if (!(ic.Value is int))
                {
                    throw new ParserException(ic.FirstToken, "Enum values must resolve into integers. This does not.");
                }

                this.ValuesByName[cycleKey] = ic;
                cycleDetection.Remove(cycleKey);
            }
        }
示例#11
0
        public override Expression ResolveNamesAndCullUnusedCode(PastelCompiler compiler)
        {
            this.Root = this.Root.ResolveNamesAndCullUnusedCode(compiler);

            if (this.Root is EnumReference)
            {
                InlineConstant enumValue = ((EnumReference)this.Root).EnumDef.GetValue(this.FieldName);
                return(enumValue.CloneWithNewToken(this.FirstToken));
            }

            if (this.Root is DependencyNamespaceReference)
            {
                PastelCompiler     dependencyScope = ((DependencyNamespaceReference)this.Root).Scope;
                string             field           = this.FieldName.Value;
                FunctionDefinition funcDef         = dependencyScope.GetFunctionDefinition(field);
                if (funcDef != null)
                {
                    return(new FunctionReference(this.FirstToken, funcDef, this.Owner));
                }

                EnumDefinition enumDef = dependencyScope.GetEnumDefinition(field);
                if (enumDef != null)
                {
                    return(new EnumReference(this.FirstToken, enumDef, this.Owner));
                }

                InlineConstant constValue = dependencyScope.GetConstantDefinition(field);
                if (constValue != null)
                {
                    return(constValue.CloneWithNewTokenAndOwner(this.FirstToken, this.Owner));
                }

                throw new ParserException(this.FieldName, "The namespace '" + ((DependencyNamespaceReference)this.Root).FirstToken.Value + "' does not have a member called '" + field + "'");
            }

            if (this.Root is CoreNamespaceReference)
            {
                CoreFunction coreFunction = this.GetCoreFunction(this.FieldName.Value);
                switch (coreFunction)
                {
                case CoreFunction.FLOAT_BUFFER_16:
                case CoreFunction.INT_BUFFER_16:
                case CoreFunction.STRING_BUFFER_16:
                    return(new CoreFunctionInvocation(this.FirstToken, coreFunction, new Expression[0], this.Owner));

                default:
                    return(new CoreFunctionReference(this.FirstToken, coreFunction, this.Owner));
                }
            }

            if (this.Root is ExtensibleNamespaceReference)
            {
                string name = this.FieldName.Value;
                return(new ExtensibleFunctionReference(this.FirstToken, name, this.Owner));
            }

            if (this.Root is EnumReference)
            {
                EnumDefinition enumDef   = ((EnumReference)this.Root).EnumDef;
                InlineConstant enumValue = enumDef.GetValue(this.FieldName);
                return(enumValue);
            }

            return(this);
        }
示例#12
0
        internal override Expression ResolveWithTypeContext(PastelCompiler compiler)
        {
            for (int i = 0; i < this.Expressions.Length; ++i)
            {
                this.Expressions[i] = this.Expressions[i].ResolveWithTypeContext(compiler);
            }

            InlineConstant left  = this.Expressions[0] as InlineConstant;
            InlineConstant right = this.Expressions[1] as InlineConstant;

            while (left != null && right != null)
            {
                object leftValue  = left.Value;
                object rightValue = right.Value;
                string lookup     = left.ResolvedType.RootValue + this.Ops[0].Value + right.ResolvedType.RootValue;
                switch (lookup)
                {
                case "int+int": this.Expressions[0] = CreateInteger(left.FirstToken, (int)leftValue + (int)rightValue); break;

                case "int-int": this.Expressions[0] = CreateInteger(left.FirstToken, (int)leftValue - (int)rightValue); break;

                case "int*int": this.Expressions[0] = CreateInteger(left.FirstToken, (int)leftValue * (int)rightValue); break;

                case "int/int": this.Expressions[0] = CreateInteger(left.FirstToken, (int)leftValue / (int)rightValue); break;

                case "int+double": this.Expressions[0] = CreateFloat(left.FirstToken, (int)leftValue + (double)rightValue); break;

                case "int-double": this.Expressions[0] = CreateFloat(left.FirstToken, (int)leftValue - (double)rightValue); break;

                case "int*double": this.Expressions[0] = CreateFloat(left.FirstToken, (int)leftValue * (double)rightValue); break;

                case "int/double": this.Expressions[0] = CreateFloat(left.FirstToken, (int)leftValue / (double)rightValue); break;

                case "double+int": this.Expressions[0] = CreateFloat(left.FirstToken, (double)leftValue + (int)rightValue); break;

                case "double-int": this.Expressions[0] = CreateFloat(left.FirstToken, (double)leftValue - (int)rightValue); break;

                case "double*int": this.Expressions[0] = CreateFloat(left.FirstToken, (double)leftValue * (int)rightValue); break;

                case "double/int": this.Expressions[0] = CreateFloat(left.FirstToken, (double)leftValue / (int)rightValue); break;

                case "double+double": this.Expressions[0] = CreateFloat(left.FirstToken, (double)leftValue + (double)rightValue); break;

                case "double-double": this.Expressions[0] = CreateFloat(left.FirstToken, (double)leftValue - (double)rightValue); break;

                case "double*double": this.Expressions[0] = CreateFloat(left.FirstToken, (double)leftValue * (double)rightValue); break;

                case "double/double": this.Expressions[0] = CreateFloat(left.FirstToken, (double)leftValue / (double)rightValue); break;

                case "bool&&bool": this.Expressions[0] = CreateBoolean(left.FirstToken, (bool)leftValue && (bool)rightValue); break;

                case "bool||bool": this.Expressions[0] = CreateBoolean(left.FirstToken, (bool)leftValue || (bool)rightValue); break;

                default:
                    if (this.Ops[0].Value == "%")
                    {
                        throw new NotImplementedException("Remember when you implement this to prevent negatives.");
                    }
                    throw new ParserException(this.Ops[0], "The operator is not defined for these two constants.");
                }
                List <Expression> expressions = new List <Expression>(this.Expressions);
                expressions.RemoveAt(1); // I know, I know...
                this.Expressions = expressions.ToArray();

                if (this.Expressions.Length == 1)
                {
                    return(this.Expressions[0]);
                }
                List <Token> ops = new List <Token>(this.Ops);
                ops.RemoveAt(0);
                this.Ops = ops.ToArray();
                left     = this.Expressions[0] as InlineConstant;
                right    = this.Expressions[1] as InlineConstant;
            }
            return(this);
        }
示例#13
0
        internal override Expression ResolveWithTypeContext(PastelCompiler compiler)
        {
            for (int i = 0; i < this.Expressions.Length; ++i)
            {
                this.Expressions[i] = this.Expressions[i].ResolveWithTypeContext(compiler);
            }

            InlineConstant left  = this.Expressions[0] as InlineConstant;
            InlineConstant right = this.Expressions[1] as InlineConstant;

            while (left != null && right != null)
            {
                object leftValue  = left.Value;
                object rightValue = right.Value;
                string lookup     = left.ResolvedType.RootValue + this.Ops[0].Value + right.ResolvedType.RootValue;
                switch (lookup)
                {
                case "int+int": this.Expressions[0] = CreateInteger(left.FirstToken, (int)leftValue + (int)rightValue); break;

                case "int-int": this.Expressions[0] = CreateInteger(left.FirstToken, (int)leftValue - (int)rightValue); break;

                case "int*int": this.Expressions[0] = CreateInteger(left.FirstToken, (int)leftValue * (int)rightValue); break;

                case "int/int": this.Expressions[0] = CreateInteger(left.FirstToken, (int)leftValue / (int)rightValue); break;

                case "int+double": this.Expressions[0] = CreateFloat(left.FirstToken, (int)leftValue + (double)rightValue); break;

                case "int-double": this.Expressions[0] = CreateFloat(left.FirstToken, (int)leftValue - (double)rightValue); break;

                case "int*double": this.Expressions[0] = CreateFloat(left.FirstToken, (int)leftValue * (double)rightValue); break;

                case "int/double": this.Expressions[0] = CreateFloat(left.FirstToken, (int)leftValue / (double)rightValue); break;

                case "double+int": this.Expressions[0] = CreateFloat(left.FirstToken, (double)leftValue + (int)rightValue); break;

                case "double-int": this.Expressions[0] = CreateFloat(left.FirstToken, (double)leftValue - (int)rightValue); break;

                case "double*int": this.Expressions[0] = CreateFloat(left.FirstToken, (double)leftValue * (int)rightValue); break;

                case "double/int": this.Expressions[0] = CreateFloat(left.FirstToken, (double)leftValue / (int)rightValue); break;

                case "double+double": this.Expressions[0] = CreateFloat(left.FirstToken, (double)leftValue + (double)rightValue); break;

                case "double-double": this.Expressions[0] = CreateFloat(left.FirstToken, (double)leftValue - (double)rightValue); break;

                case "double*double": this.Expressions[0] = CreateFloat(left.FirstToken, (double)leftValue * (double)rightValue); break;

                case "double/double": this.Expressions[0] = CreateFloat(left.FirstToken, (double)leftValue / (double)rightValue); break;

                case "bool&&bool": this.Expressions[0] = CreateBoolean(left.FirstToken, (bool)leftValue && (bool)rightValue); break;

                case "bool||bool": this.Expressions[0] = CreateBoolean(left.FirstToken, (bool)leftValue || (bool)rightValue); break;

                default:
                    if (this.Ops[0].Value == "%")
                    {
                        throw new NotImplementedException("Remember when you implement this to prevent negatives.");
                    }
                    throw new ParserException(this.Ops[0], "The operator is not defined for these two constants.");
                }
                List <Expression> expressions = new List <Expression>(this.Expressions);
                expressions.RemoveAt(1); // I know, I know...
                this.Expressions = expressions.ToArray();

                if (this.Expressions.Length == 1)
                {
                    return(this.Expressions[0]);
                }
                List <Token> ops = new List <Token>(this.Ops);
                ops.RemoveAt(0);
                this.Ops = ops.ToArray();
                left     = this.Expressions[0] as InlineConstant;
                right    = this.Expressions[1] as InlineConstant;
            }

            // TODO(pastel-split): This is just a quick and dirty short-circuit logic for && and ||
            // Do full logic later. Currently this is causing problems in specific snippets in Crayon libraries.
            string opValue = this.Ops[0].Value;

            if (left != null)
            {
                if (opValue == "&&" && left.Value is bool)
                {
                    return((bool)left.Value ? (Expression)this : left);
                }
                if (opValue == "||" && left.Value is bool)
                {
                    return((bool)left.Value ? left : (Expression)this);
                }
            }

            return(this);
        }