Example #1
0
        public override string TranslateType(Pastel.Nodes.PType type)
        {
            switch (type.RootValue)
            {
            case "int":
            case "char":
            case "bool":
            case "double":
            case "string":
            case "object":
            case "void":
                return(type.RootValue);

            case "List":
                return("List<" + this.TranslateType(type.Generics[0]) + ">");

            case "Dictionary":
                return("Dictionary<" + this.TranslateType(type.Generics[0]) + ", " + this.TranslateType(type.Generics[1]) + ">");

            case "Array":
                return(this.TranslateType(type.Generics[0]) + "[]");

            default:
                if (type.Generics.Length > 0)
                {
                    throw new NotImplementedException();
                }
                return(type.RootValue);
            }
        }
Example #2
0
        internal override Expression ResolveType(VariableScope varScope, PastelCompiler compiler)
        {
            PType type = varScope.GetTypeOfVariable(this.Name);

            this.ResolvedType = type;
            if (type == null)
            {
                throw new ParserException(
                          this.FirstToken,
                          "The " + (this.IsFunctionInvocation ? "function" : "variable") + " '" + this.Name + "' is not defined.");
            }

            return(this);
        }
Example #3
0
        internal bool IsIdentical(PastelCompiler compiler, PType other)
        {
            if (!this.isTypeFinalized)
            {
                this.FinalizeType(compiler);
            }
            if (!other.isTypeFinalized)
            {
                other.FinalizeType(compiler);
            }

            if (this.Category != other.Category)
            {
                return(false);
            }

            if (this.Generics.Length != other.Generics.Length)
            {
                return(false);
            }

            if (this.IsStructOrClass)
            {
                return(this.structReference == other.structReference || this.classReference == other.classReference);
            }

            if (this.RootValue != other.RootValue)
            {
                string thisRoot = this.RootValue;
                string thatRoot = other.RootValue;
                if (thisRoot == "number" && (thatRoot == "double" || thatRoot == "int"))
                {
                    return(true);
                }
                if (thatRoot == "number" && (thisRoot == "double" || thisRoot == "int"))
                {
                    return(true);
                }
                return(false);
            }

            for (int i = this.Generics.Length - 1; i >= 0; --i)
            {
                if (!this.Generics[i].IsIdentical(compiler, other.Generics[i]))
                {
                    return(false);
                }
            }
            return(true);
        }
Example #4
0
 public StructDefinition(Token structToken, Token name, IList <PType> argTypes, IList <Token> argNames)
 {
     this.FirstToken     = structToken;
     this.NameToken      = name;
     this.ArgTypes       = argTypes.ToArray();
     this.ArgNames       = argNames.ToArray();
     this.ArgIndexByName = new Dictionary <string, int>();
     for (int i = this.ArgNames.Length - 1; i >= 0; --i)
     {
         string argName = this.ArgNames[i].Value;
         this.ArgIndexByName[argName] = i;
     }
     this.Type = new PType(this.FirstToken, name.Value);
 }
 public FunctionDefinition(
     Token nameToken,
     PType returnType,
     IList <PType> argTypes,
     IList <Token> argNames,
     IList <Executable> code)
 {
     this.FirstToken = returnType.FirstToken;
     this.NameToken  = nameToken;
     this.ReturnType = returnType;
     this.ArgTypes   = argTypes.ToArray();
     this.ArgNames   = argNames.ToArray();
     this.Code       = code.ToArray();
 }
Example #6
0
        private void VerifyArgTypes(PType[] expectedTypes, PastelCompiler compiler)
        {
            if (expectedTypes.Length != this.Args.Length)
            {
                throw new ParserException(this.OpenParenToken, "This function invocation has the wrong number of parameters. Expected " + expectedTypes.Length + " but found " + this.Args.Length + ".");
            }

            for (int i = 0; i < this.Args.Length; ++i)
            {
                if (!PType.CheckAssignment(compiler, expectedTypes[i], this.Args[i].ResolvedType))
                {
                    throw new ParserException(this.Args[i].FirstToken, "Wrong function arg type. Cannot convert a " + this.Args[i].ResolvedType + " to a " + expectedTypes[i]);
                }
            }
        }
Example #7
0
        internal override Expression ResolveType(VariableScope varScope, PastelCompiler compiler)
        {
            for (int i = 0; i < this.Args.Length; ++i)
            {
                this.Args[i] = this.Args[i].ResolveType(varScope, compiler);
            }

            this.Root = this.Root.ResolveType(varScope, compiler);

            if (this.Root is FunctionReference)
            {
                FunctionDefinition functionDefinition = ((FunctionReference)this.Root).Function;
                this.VerifyArgTypes(functionDefinition.ArgTypes, compiler);
                this.ResolvedType = functionDefinition.ReturnType;
                return(this);
            }
            else if (this.Root is CoreFunctionReference)
            {
                CoreFunctionReference  nfr = (CoreFunctionReference)this.Root;
                CoreFunctionInvocation nfi;
                if (nfr.Context == null)
                {
                    nfi = new CoreFunctionInvocation(this.FirstToken, nfr.CoreFunctionId, this.Args, this.Owner);
                }
                else
                {
                    nfi = new CoreFunctionInvocation(this.FirstToken, nfr.CoreFunctionId, nfr.Context, this.Args, this.Owner);
                }

                return(nfi.ResolveType(varScope, compiler));
            }
            else if (this.Root is ExtensibleFunctionReference)
            {
                return(new ExtensibleFunctionInvocation(this.FirstToken, (ExtensibleFunctionReference)this.Root, this.Args).ResolveType(varScope, compiler));
            }
            else if (this.Root is ConstructorReference)
            {
                PType typeToConstruct = ((ConstructorReference)this.Root).TypeToConstruct;
                typeToConstruct.FinalizeType(compiler);
                return(new ConstructorInvocation(this.FirstToken, typeToConstruct, this.Args, this.Owner));
            }
            else if (this.Root.ResolvedType.RootValue == "Func")
            {
                return(new FunctionPointerInvocation(compiler, this.FirstToken, this.Root, this.Args));
            }

            throw new ParserException(this.OpenParenToken, "This expression cannot be invoked like a function.");
        }
Example #8
0
 public FunctionDefinition(
     Token nameToken,
     PType returnType,
     IList <PType> argTypes,
     IList <Token> argNames,
     PastelContext context,
     ClassDefinition nullableClassOwner) // null if not associated with a class
 {
     this.Context    = context;
     this.FirstToken = returnType.FirstToken;
     this.NameToken  = nameToken;
     this.ReturnType = returnType;
     this.ArgTypes   = argTypes.ToArray();
     this.ArgNames   = argNames.ToArray();
     this.ClassDef   = nullableClassOwner;
 }
Example #9
0
 internal override void ResolveTypes(VariableScope varScope, PastelCompiler compiler)
 {
     if (this.Expression != null)
     {
         this.Expression = this.Expression.ResolveType(varScope, compiler);
         if (!PType.CheckReturnType(varScope.RootFunctionDefinition.ReturnType, this.Expression.ResolvedType))
         {
             throw new ParserException(this.Expression.FirstToken, "This expression is not the expected return type of this function.");
         }
     }
     else
     {
         if (!this.Expression.ResolvedType.IsIdentical(PType.VOID))
         {
             throw new ParserException(this.FirstToken, "Must return a value in this function.");
         }
     }
 }
Example #10
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);
        }
Example #11
0
        public override string TranslateType(Pastel.Nodes.PType type)
        {
            switch (type.RootValue)
            {
            case "int": return("int");

            case "string": return("int*");

            case "bool": return("int");

            case "double": return("double");

            case "object": return("void*");

            case "char": return("int");

            case "List": return("List*");

            case "Array": return(this.TranslateType(type.Generics[0]) + "*");

            case "Dictionary":
                string keyType = type.Generics[0].RootValue;
                switch (keyType)
                {
                case "int":
                case "string":
                    return("Dictionary*");

                default:
                    throw new NotImplementedException();
                }

            default: break;
            }

            char firstChar = type.RootValue[0];

            if (firstChar >= 'A' && firstChar <= 'Z')
            {
                return(type.RootValue + "*");
            }

            throw new NotImplementedException();
        }
Example #12
0
        internal override void ResolveTypes(VariableScope varScope, PastelCompiler compiler)
        {
            this.Value  = this.Value.ResolveType(varScope, compiler);
            this.Target = this.Target.ResolveType(varScope, compiler);

            if (!PType.CheckAssignment(this.Target.ResolvedType, this.Value.ResolvedType))
            {
                if (this.OpToken.Value != "=" &&
                    this.Target.ResolvedType.IsIdentical(PType.DOUBLE) &&
                    this.Value.ResolvedType.IsIdentical(PType.INT))
                {
                    // You can apply incremental ops such as += with an int to a float and that is fine without explicit conversion in any platform.
                }
                else
                {
                    throw new ParserException(this.OpToken, "Cannot assign a " + this.Value.ResolvedType + " to a " + this.Target.ResolvedType);
                }
            }
        }
Example #13
0
        private bool IsParentOf(PType moreSpecificTypeOrSame)
        {
            if (moreSpecificTypeOrSame == this)
            {
                return(true);
            }
            if (this.RootValue == "object")
            {
                return(true);
            }
            if (this.Generics.Length == 0)
            {
                // why no treatment of int as a subtype of double? because there needs to be an explicit type conversion
                // for languages that aren't strongly typed and won't auto-convert.
                return(this.RootValue == moreSpecificTypeOrSame.RootValue);
            }

            // All that's left are Arrays, Lists, and Dictionaries, which must match exactly.
            return(this.IsIdentical(moreSpecificTypeOrSame));
        }
Example #14
0
        internal bool IsIdenticalOrChildOf(PastelCompiler compiler, PType other)
        {
            if (this.IsIdentical(compiler, other))
            {
                return(true);
            }

            // only structs or classes should be here if this is to return true. If not, then it's a no.
            if (!this.IsStructOrClass || !other.IsStructOrClass)
            {
                return(false);
            }

            if (this.IsStruct != other.IsStruct)
            {
                return(false);
            }
            if (this.IsStruct)
            {
                if (this.StructDef == null || other.StructDef == null)
                {
                    throw new System.Exception("This check cannot occur without resolving struct information for PTypes.");
                }
                StructDefinition walker = this.StructDef;
                StructDefinition target = other.StructDef;
                while (walker != null)
                {
                    if (walker == target)
                    {
                        return(true);
                    }
                    walker = walker.Parent;
                }
            }
            if (this.IsClass)
            {
                throw new System.NotImplementedException();
            }

            return(false);
        }
        // Note that this class is instantiated in the ResolveType phase.
        public FunctionPointerInvocation(PastelCompiler compiler, Token firstToken, Expression root, IList <Expression> Args)
            : base(firstToken, root.Owner)
        {
            this.Root = root;
            this.Args = Args.ToArray();

            this.ResolvedType = this.Root.ResolvedType.Generics[0];

            if (this.Root.ResolvedType.Generics.Length - 1 != this.Args.Length)
            {
                throw new ParserException(this.Root.FirstToken, "This function has the incorrect number of arguments.");
            }
            for (int i = 0; i < this.Args.Length; ++i)
            {
                PType expectedArgType = this.Root.ResolvedType.Generics[i + 1];
                PType actualArgType   = this.Args[i].ResolvedType;
                if (!actualArgType.IsIdentical(compiler, expectedArgType))
                {
                    throw new ParserException(this.Args[i].FirstToken, "Incorrect argument type. Expected " + expectedArgType + " but found " + actualArgType + ".");
                }
            }
        }
Example #16
0
        internal override Expression ResolveType(VariableScope varScope, PastelCompiler compiler)
        {
            ClassDefinition cd;

            if (this.Owner is FunctionDefinition funcDef)
            {
                cd = funcDef.ClassDef;
            }
            else if (this.Owner is FieldDefinition fieldDef)
            {
                cd = fieldDef.ClassDef;
            }
            else if (this.Owner is ConstructorDefinition constructorDef)
            {
                cd = constructorDef.ClassDef;
            }
            else
            {
                throw new ParserException(this.FirstToken, "Cannot use the expression 'this' outside of classes.");
            }
            this.ResolvedType = PType.ForClass(this.FirstToken, cd);
            return(this);
        }
Example #17
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;
            }
            else
            {
                badIndex = true;
            }

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

            return(this);
        }
Example #18
0
        internal static bool CheckReturnType(PastelCompiler compiler, PType returnType, PType value)
        {
            // This is an assert, not a user-facing exception. Null should never appear here.
            if (value == null)
            {
                throw new ParserException(returnType.FirstToken, "This should not happen.");
            }

            if (value.IsIdenticalOrChildOf(compiler, returnType))
            {
                return(true);
            }
            if (returnType.Category == TypeCategory.OBJECT)
            {
                return(true);
            }
            if (returnType.Category == TypeCategory.VOID)
            {
                return(false);
            }
            if (value.Category == TypeCategory.NULL)
            {
                if (returnType.Category == TypeCategory.PRIMITIVE && returnType.TypeName == "string")
                {
                    return(true);
                }
                if (returnType.Generics.Length > 0)
                {
                    return(true);
                }
                if (returnType.IsStructOrClass)
                {
                    return(true);
                }
            }
            return(false);
        }
        internal override Expression ResolveType(VariableScope varScope, PastelCompiler compiler)
        {
            // The args were already resolved.
            // This ensures that they match the native function definition

            PType[] expectedTypes = NativeFunctionUtil.GetNativeFunctionArgTypes(this.Function);
            bool[]  isArgRepeated = NativeFunctionUtil.GetNativeFunctionIsArgTypeRepeated(this.Function);

            switch (this.Function)
            {
            case NativeFunction.FORCE_PARENS:
                if (this.Args.Length != 1)
                {
                    throw new ParserException(this.FirstToken, "Expected 1 arg.");
                }

                return(new ForcedParenthesis(this.FirstToken, this.Args[0]));

            case NativeFunction.IS_DEBUG:
#if DEBUG
                bool value = true;
#else
                bool value = false;
#endif
                return(new InlineConstant(PType.BOOL, this.FirstToken, value));
            }

            Dictionary <string, PType> templateLookup = new Dictionary <string, PType>();

            int verificationLength = expectedTypes.Length;
            if (verificationLength > 0 && isArgRepeated[isArgRepeated.Length - 1])
            {
                verificationLength--;
            }

            for (int i = 0; i < verificationLength; ++i)
            {
                if (!PType.CheckAssignmentWithTemplateOutput(expectedTypes[i], this.Args[i].ResolvedType, templateLookup))
                {
                    throw new ParserException(this.Args[i].FirstToken, "Incorrect type. Expected " + expectedTypes[i] + " but found " + this.Args[i].ResolvedType + ".");
                }
            }

            if (expectedTypes.Length < this.Args.Length)
            {
                if (isArgRepeated[isArgRepeated.Length - 1])
                {
                    PType expectedType = expectedTypes[expectedTypes.Length - 1];
                    for (int i = expectedTypes.Length; i < this.Args.Length; ++i)
                    {
                        if (!PType.CheckAssignment(expectedType, this.Args[i].ResolvedType))
                        {
                            throw new ParserException(this.Args[i].FirstToken, "Incorrect type. Expected " + expectedTypes[i] + " but found " + this.Args[i].ResolvedType + ".");
                        }
                    }
                }
                else
                {
                    throw new ParserException(this.FirstToken, "Too many arguments.");
                }
            }

            PType returnType = NativeFunctionUtil.GetNativeFunctionReturnType(this.Function);

            if (returnType.HasTemplates)
            {
                returnType = returnType.ResolveTemplates(templateLookup);
            }

            this.ResolvedType = returnType;

            return(this);
        }
Example #20
0
        private NativeFunction DetermineNativeFunctionId(PType rootType, string field)
        {
            switch (rootType.RootValue)
            {
            case "string":
                switch (field)
                {
                case "CharCodeAt": return(NativeFunction.STRING_CHAR_CODE_AT);

                case "Contains": return(NativeFunction.STRING_CONTAINS);

                case "EndsWith": return(NativeFunction.STRING_ENDS_WITH);

                case "IndexOf": return(NativeFunction.STRING_INDEX_OF);

                case "Replace": return(NativeFunction.STRING_REPLACE);

                case "Reverse": return(NativeFunction.STRING_REVERSE);

                case "Size": return(NativeFunction.STRING_LENGTH);

                case "Split": return(NativeFunction.STRING_SPLIT);

                case "StartsWith": return(NativeFunction.STRING_STARTS_WITH);

                case "SubString": return(NativeFunction.STRING_SUBSTRING);

                case "SubStringIsEqualTo": return(NativeFunction.STRING_SUBSTRING_IS_EQUAL_TO);

                case "ToLower": return(NativeFunction.STRING_TO_LOWER);

                case "ToUpper": return(NativeFunction.STRING_TO_UPPER);

                case "Trim": return(NativeFunction.STRING_TRIM);

                case "TrimEnd": return(NativeFunction.STRING_TRIM_END);

                case "TrimStart": return(NativeFunction.STRING_TRIM_START);

                default: throw new ParserException(this.FieldName, "Unresolved string method: " + field);
                }

            case "Array":
                switch (field)
                {
                case "Join": return(NativeFunction.ARRAY_JOIN);

                case "Size": return(NativeFunction.ARRAY_LENGTH);

                default: throw new ParserException(this.FieldName, "Unresolved Array method: " + field);
                }

            case "List":
                switch (field)
                {
                case "Add": return(NativeFunction.LIST_ADD);

                case "Clear": return(NativeFunction.LIST_CLEAR);

                case "Insert": return(NativeFunction.LIST_INSERT);

                case "Join":
                    string memberType = rootType.Generics[0].RootValue;
                    switch (memberType)
                    {
                    case "string": return(NativeFunction.LIST_JOIN_STRINGS);

                    case "char": return(NativeFunction.LIST_JOIN_CHARS);

                    default: throw new ParserException(this.FieldName, "Unresolved List<" + memberType + "> method: " + field);
                    }

                case "Pop": return(NativeFunction.LIST_POP);

                case "RemoveAt": return(NativeFunction.LIST_REMOVE_AT);

                case "Reverse": return(NativeFunction.LIST_REVERSE);

                case "Shuffle": return(NativeFunction.LIST_SHUFFLE);

                case "Size": return(NativeFunction.LIST_SIZE);

                default: throw new ParserException(this.FieldName, "Unresolved List method: " + field);
                }

            case "Dictionary":
                switch (field)
                {
                case "Contains": return(NativeFunction.DICTIONARY_CONTAINS_KEY);

                case "Keys": return(NativeFunction.DICTIONARY_KEYS);

                case "Remove": return(NativeFunction.DICTIONARY_REMOVE);

                case "Size": return(NativeFunction.DICTIONARY_SIZE);

                case "Values": return(NativeFunction.DICTIONARY_VALUES);

                default: throw new ParserException(this.FieldName, "Unresolved Dictionary method: " + field);
                }

            default:
                throw new ParserException(this.FieldName, "Unresolved field.");
            }
        }
Example #21
0
 public ConstructorReference(Token newToken, PType type, ICompilationEntity owner) : base(newToken, owner)
 {
     this.TypeToConstruct = type;
 }
Example #22
0
        // when a templated type coincides with an actual value, add that template key to the lookup output param.
        public static bool CheckAssignmentWithTemplateOutput(PType templatedType, PType actualValue, Dictionary <string, PType> output)
        {
            if (templatedType.RootValue == "object")
            {
                return(true);
            }

            // Most cases, nothing to do
            if (templatedType.IsIdentical(actualValue))
            {
                return(true);
            }

            if (templatedType.RootValue.Length == 1)
            {
                if (output.ContainsKey(templatedType.RootValue))
                {
                    PType requiredType = output[templatedType.RootValue];
                    // if it's already encountered it better match the existing value
                    if (actualValue.IsIdentical(requiredType))
                    {
                        return(true);
                    }

                    // It's also possible that this is null, in which case the type must be nullable.
                    if (actualValue.RootValue == "null" && requiredType.IsNullable)
                    {
                        return(true);
                    }

                    return(false);
                }
                output[templatedType.RootValue] = actualValue;
                return(true);
            }

            if (templatedType.Generics.Length != actualValue.Generics.Length)
            {
                // completely different. don't even try to match templates
                return(false);
            }

            if (templatedType.RootValue != actualValue.RootValue)
            {
                if (templatedType.RootValue.Length == 1)
                {
                    if (output.ContainsKey(templatedType.RootValue))
                    {
                        // if it's already encountered it better match the existing value
                        if (actualValue.IsIdentical(output[templatedType.RootValue]))
                        {
                            // yup, that's okay
                        }
                        else
                        {
                            return(false);
                        }
                    }
                    else
                    {
                        // first time this type was encountered.
                        output[templatedType.RootValue] = actualValue;
                    }
                }
                else
                {
                    // different type
                    return(false);
                }
            }

            for (int i = 0; i < templatedType.Generics.Length; ++i)
            {
                if (!CheckAssignmentWithTemplateOutput(templatedType.Generics[i], actualValue.Generics[i], output))
                {
                    return(false);
                }
            }

            return(true);
        }
Example #23
0
 public ConstructorReference(Token newToken, PType type) : base(newToken)
 {
     this.TypeToConstruct = type;
 }
Example #24
0
        private static PType ParseImpl(TokenStream tokens)
        {
            Token token = tokens.Pop();

            switch (token.Value)
            {
            case "int":
            case "char":
            case "double":
            case "bool":
            case "void":
            case "string":
            case "object":
                return(new PType(token, token.Value));

            default:
                if (!PastelParser.IsValidName(token.Value))
                {
                    return(null);
                }
                break;
            }

            int  tokenIndex = tokens.SnapshotState();
            bool isError    = false;

            if (tokens.PopIfPresent("<"))
            {
                List <PType> generics = new List <PType>();
                while (!tokens.PopIfPresent(">"))
                {
                    if (generics.Count > 0)
                    {
                        if (!tokens.PopIfPresent(","))
                        {
                            isError = true;
                            break;
                        }
                    }

                    PType generic = ParseImpl(tokens);
                    if (generic == null)
                    {
                        return(null);
                    }

                    generics.Add(generic);
                }
                if (!isError)
                {
                    return(new PType(token, token.Value, generics));
                }

                // If there was an error while parsing generics, then this may still be a valid type.
                tokens.RevertState(tokenIndex);
                return(new PType(token, token.Value));
            }
            else
            {
                return(new PType(token, token.Value));
            }
        }
Example #25
0
        internal override Expression ResolveType(VariableScope varScope, PastelCompiler compiler)
        {
            for (int i = 0; i < this.Expressions.Length; ++i)
            {
                this.Expressions[i] = this.Expressions[i].ResolveType(varScope, compiler);
            }

            this.ResolvedType = this.Expressions[0].ResolvedType;

            for (int i = 0; i < this.Ops.Length; ++i)
            {
                PType  nextType = this.Expressions[i + 1].ResolvedType;
                string op       = this.Ops[i].Value;
                if (op == "==" || op == "!=")
                {
                    if ((nextType.RootValue == this.ResolvedType.RootValue) ||
                        (nextType.RootValue == "null" && this.ResolvedType.IsNullable) ||
                        (nextType.IsNullable && this.ResolvedType.RootValue == "null") ||
                        (nextType.RootValue == "null" && this.ResolvedType.RootValue == "null"))
                    {
                        this.ResolvedType = PType.BOOL;
                        continue;
                    }
                }
                string lookup = this.ResolvedType.RootValue + this.Ops[i].Value + nextType.RootValue;
                switch (lookup)
                {
                case "int+int":
                case "int-int":
                case "int*int":
                case "int%int":
                case "int&int":
                case "int|int":
                case "int^int":
                case "int<<int":
                case "int>>int":
                    this.ResolvedType = PType.INT;
                    break;

                case "int+double":
                case "double+int":
                case "double+double":
                case "int-double":
                case "double-int":
                case "double-double":
                case "int*double":
                case "double*int":
                case "double*double":
                case "double%int":
                case "int%double":
                case "double%double":
                    this.ResolvedType = PType.DOUBLE;
                    break;

                case "int>int":
                case "int<int":
                case "int>=int":
                case "int<=int":
                case "double<int":
                case "double>int":
                case "double<=int":
                case "double>=int":
                case "int<double":
                case "int>double":
                case "int<=double":
                case "int>=double":
                case "double<double":
                case "double>double":
                case "double<=double":
                case "double>=double":
                case "int==int":
                case "double==double":
                case "int==double":
                case "double==int":
                case "int!=int":
                case "double!=double":
                case "int!=double":
                case "double!=int":
                case "bool&&bool":
                case "bool||bool":
                case "char>char":
                case "char<char":
                case "char>=char":
                case "char<=char":
                    this.ResolvedType = PType.BOOL;
                    break;

                case "int/int":
                case "int/double":
                case "double/int":
                case "double/double":
                    throw new ParserException(this.Ops[i], "Due to varying platform behavior of / use Core.IntegerDivision(numerator, denominator) or Core.FloatDivision(numerator, denominator)");

                default:
                    throw new ParserException(this.Ops[i], "The operator '" + this.Ops[i].Value + "' is not defined for types: " + this.ResolvedType + " and " + nextType + ".");
                }
            }
            return(this);
        }
Example #26
0
 public override string TranslateType(Pastel.Nodes.PType type)
 {
     return(this.ParentPlatform.TranslateType(type));
 }
Example #27
0
 public CastExpression(Token openParenToken, PType type, Expression expression) : base(openParenToken)
 {
     this.Type       = type;
     this.Expression = expression;
 }
Example #28
0
 public ConstructorInvocation(Token firstToken, PType type, IList <Expression> args) : base(firstToken)
 {
     this.Type         = type;
     this.Args         = args.ToArray();
     this.ResolvedType = type;
 }
Example #29
0
 public InlineConstant(PType type, Token firstToken, object value) : base(firstToken)
 {
     this.Type         = type;
     this.ResolvedType = type;
     this.Value        = value;
 }
Example #30
0
 public InlineConstant(PType type, Token firstToken, object value, ICompilationEntity owner) : base(firstToken, owner)
 {
     this.Type         = type;
     this.ResolvedType = type;
     this.Value        = value;
 }