Exemple #1
0
        public bool IsEqual(TypeRecord rec)
        {
            if (!string.IsNullOrEmpty(this.Identifer))
            {
                if (!string.IsNullOrEmpty(rec.Identifer))
                {
                    return(this.Identifer == rec.Identifer);
                }
            }

            return((this.Module + ":" + this.Symbol) == (rec.Module + ":" + rec.Symbol));
        }
Exemple #2
0
        public void Evaluate(AnalysisEnvironment environment)
        {
            if (IsEvaluated)
            {
                return;
            }

            TypeRecord temp = this.Combination[0];

            for (int i = 1; i < this.Combination.Count; i++)
            {
                temp = Combine(environment, temp, this.Combination[i]);
            }

            if (temp is AnyType)
            {
                this.Identifer          = "any";
                this.ClrTypeRecordIndex = -3;
                this.IsEvaluated        = true;
            }
            else
            {
                foreach (var item in temp.FieldSymbols)
                {
                    this.FieldSymbols.Add(item.Key, item.Value);
                }
                foreach (var item in temp.FieldTypes)
                {
                    this.FieldTypes.Add(item);
                }
                foreach (var item in temp.MemberFunctions)
                {
                    if (!this.MemberFunctions.ContainsKey(item.Key))
                    {
                        this.MemberFunctions.Add(item.Key, item.Value);
                    }
                }

                this.IsEvaluated = true;
                this.GetIdentifer(this, environment);
            }
        }
Exemple #3
0
        public TypeRecord Combine(AnalysisEnvironment environment, TypeRecord Target, TypeRecord Addition)
        {
            if (Target is IOperationType operation)
            {
                operation.Evaluate(environment);
            }

            if (Addition is IOperationType exclusion)
            {
                exclusion.Evaluate(environment);
            }

            if (Target.ClrTypeRecordIndex == -1)
            {
                Target.GetIdentifer(this, environment);
            }
            if (Addition.ClrTypeRecordIndex == -1)
            {
                Addition.GetIdentifer(this, environment);
            }

            if (Target is AnyType ||
                Addition is AnyType)
            {
                return(new AnyType());
            }

            TypeRecord typeRecord = new TypeRecord();

            foreach (var item in Target.FieldSymbols)
            {
                typeRecord.FieldSymbols.Add(item.Key, item.Value);
            }

            foreach (var item in Target.FieldTypes)
            {
                typeRecord.FieldTypes.Add(item);
            }

            // foreach (var item in Target.MemberFunctions) {
            //    typeRecord.MemberFunctions.Add(item.Key, item.Value);
            // }

            int counter = 0;

            foreach (var item in Addition.FieldSymbols)
            {
                if (!typeRecord.FieldSymbols.ContainsKey(item.Key))
                {
                    typeRecord.FieldSymbols.Add(item.Key, item.Value);
                    typeRecord.FieldTypes.Add(Addition.FieldTypes[counter]);
                }
                counter++;
            }

            // foreach (var item in Addition.MemberFunctions) {
            //    if (!typeRecord.MemberFunctions.ContainsKey(item.Key))
            //        typeRecord.MemberFunctions.Add(item.Key, item.Value);
            // }

            typeRecord.Symbol = "___autogen_class_" + Interop.AnonymousTypeRecord.RegistryCount;
            typeRecord.GetIdentifer(typeRecord, environment);
            environment.SetObject(typeRecord.Oid, typeRecord);
            return(typeRecord);
        }
Exemple #4
0
 public override string GetIdentifer(TypeRecord caller, AnalysisEnvironment environment)
 {
     this.Identifer          = "any";
     this.ClrTypeRecordIndex = -3;
     return("any");
 }
Exemple #5
0
        public virtual string GetIdentifer(TypeRecord caller, AnalysisEnvironment environment)
        {
            // the record index is set, which means the type is successfully registered and
            // is allocated with an index already.

            if (ClrTypeRecordIndex != -1)
            {
                return("<" + ClrTypeRecordIndex + ">");
            }
            Interop.AnonymousTypeRecord.RegistryCount++;
            this.ClrTypeRecordIndex = Interop.AnonymousTypeRecord.RegistryCount;

            Interop.AnonymousTypeRecord.IdentiferRegistry.Add(this.ClrTypeRecordIndex, "(undefined)");

            int           id     = 0;
            List <string> fields = new List <string>();

            foreach (var item in this.FieldSymbols)
            {
                if (environment.Objects[item.Value] is FunctionRecord func)
                {
                    continue;
                }

                var    field          = (DataRecord)environment.Objects[item.Value];
                string fieldIdentifer = "";
                fieldIdentifer += field.Symbol + ":";
                if (this.FieldTypes[id].Symbol != (caller?.Symbol ?? ""))
                {
                    // the declaring type doesn't contains its parent type. thus, we can perform
                    // iteration (if not cached in ClrTypeRecord.Registry).

                    fieldIdentifer += this.FieldTypes[id].GetIdentifer(this, environment);
                }
                else
                {
                    // the declaring type contains its parent type. this will cause recursion, and
                    // is not allowed in compiletime. throw a warning message indicating that the
                    // reference is automatically converted to a pointer.

                    if (caller.ClrTypeRecordIndex == -1)
                    {
                        environment.Current.Diagnostics.AddFatal(Parser.SyntaxError.RecursiveAssertionFailed, new Parser.Token(""));
                    }
                    else
                    {
                        environment.Current.Diagnostics.AddWarning(Parser.SyntaxError.RecursiveToPointer, new Parser.Token(""));
                        fieldIdentifer += "{" + caller.ClrTypeRecordIndex + "}";
                    }
                }

                fields.Add(fieldIdentifer);
                id++;
            }

            fields.Sort();
            this.Identifer = "(" + fields.JoinString("|") + ")";

            // register the identifer and index in the global class cache.

            Interop.AnonymousTypeRecord.IdentiferRegistry[ClrTypeRecordIndex] = this.Identifer;
            return("<" + this.ClrTypeRecordIndex + ">");
        }
Exemple #6
0
        public bool IsCompatible(TypeRecord record)
        {
            if (this.Identifer == record.Identifer)
            {
                return(true);
            }

            switch (this.Symbol)
            {
            case "int8":
                if (record.Symbol == "int16" ||
                    record.Symbol == "int32" ||
                    record.Symbol == "int64" ||
                    record.Symbol == "float32" ||
                    record.Symbol == "float64")
                {
                    return(true);
                }
                return(false);

            case "int16":
                if (record.Symbol == "int32" ||
                    record.Symbol == "int64" ||
                    record.Symbol == "float32" ||
                    record.Symbol == "float64")
                {
                    return(true);
                }
                return(false);

            case "int32":
                if (record.Symbol == "int64" ||
                    record.Symbol == "float32" ||
                    record.Symbol == "float64")
                {
                    return(true);
                }
                return(false);

            case "int64":
                if (record.Symbol == "float32" ||
                    record.Symbol == "float64")
                {
                    return(true);
                }
                return(false);

            case "uint8":
                if (record.Symbol == "int16" ||
                    record.Symbol == "int32" ||
                    record.Symbol == "int64" ||
                    record.Symbol == "uint16" ||
                    record.Symbol == "uint32" ||
                    record.Symbol == "uint64" ||
                    record.Symbol == "float32" ||
                    record.Symbol == "float64")
                {
                    return(true);
                }
                return(false);

            case "uint16":
                if (record.Symbol == "int32" ||
                    record.Symbol == "int64" ||
                    record.Symbol == "uint32" ||
                    record.Symbol == "uint64" ||
                    record.Symbol == "float32" ||
                    record.Symbol == "float64")
                {
                    return(true);
                }
                return(false);

            case "uint32":
                if (record.Symbol == "int64" ||
                    record.Symbol == "uint64" ||
                    record.Symbol == "float32" ||
                    record.Symbol == "float64")
                {
                    return(true);
                }
                return(false);

            case "uint64":
                if (record.Symbol == "float32" ||
                    record.Symbol == "float64")
                {
                    return(true);
                }
                return(false);

            case "logical":
                if (record.Symbol == "int8" ||
                    record.Symbol == "int16" ||
                    record.Symbol == "int32" ||
                    record.Symbol == "int64" ||
                    record.Symbol == "uint8" ||
                    record.Symbol == "uint16" ||
                    record.Symbol == "uint32" ||
                    record.Symbol == "uint64" ||
                    record.Symbol == "float32" ||
                    record.Symbol == "float64")
                {
                    return(true);
                }
                return(false);

            case "float32":
                if (record.Symbol == "float64")
                {
                    return(true);
                }
                return(false);

            case "float64":
                return(false);

            case "___data":
                return(false);

            case "expr":
                return(false);

            case "matrix":
                return(false);

            case "___func":
                return(false);

            case "null":
                return(false);

            default:
                break;
            }

            bool flag = true;

            foreach (var item in this.FieldSymbols)
            {
                if (!record.FieldSymbols.ContainsKey(item.Key))
                {
                    flag = false;
                    break;
                }
            }

            int index = 0;

            foreach (var item in this.FieldSymbols)
            {
                var type           = this.FieldTypes[index];
                int recordSelected = 0;
                foreach (var recs in record.FieldSymbols)
                {
                    if (recs.Key == item.Key)
                    {
                        if (type.Identifer != record.FieldTypes[recordSelected].Identifer)
                        {
                            flag = false;
                        }
                        recordSelected++;
                    }
                }
                index++;
            }

            return(flag);
        }
Exemple #7
0
 public InternalDataType(TypeRecord record)
 {
     this.Type = record;
 }
Exemple #8
0
 public ExcludeType(TypeRecord target, TypeRecord exclusion) : this()
 {
     this.Target    = target;
     this.Exclusion = exclusion;
 }
Exemple #9
0
        private Record.TypeRecord EvalTypeExpression(IExpression expression, Dictionary <string, Record.IRecord> external,
                                                     Dictionary <int, System.Reflection.Emit.TypeBuilder> typeBuilders, Dictionary <int, System.Type> compiledTypes, Emit.ProgramBuilder programBuilder)
        {
            // 1. to locate the objects
            //    - global definitions are defined (has their names) in BaselineScope.
            //    - for regional variables (which defined inside classes, parental classes, and functions
            //      are provided manually in the external collection.

            // 2. to determine whether the selected object is field of classes and instances, or the natively
            //    or manually defined definitions.

            if (expression is Literal lit)
            {
                switch (lit.Type)
                {
                case LiteralType.Float:
                    return(this.TypeFloat64);

                case LiteralType.Integer:
                    return(this.TypeInt32);

                case LiteralType.String:
                    return(this.GetDirectTypeRecord(new Literal("string")));    // matrix(uint16)

                case LiteralType.Named:
                case LiteralType.Illegal:
                    if (lit.Value.ToLower() == "true" ||
                        lit.Value.ToLower() == "false")
                    {
                        return(this.TypeLogical);
                    }
                    if (lit.Value.ToLower() == "none")
                    {
                        return(this.TypeNull);
                    }

                    if (external.ContainsKey(lit.Value))
                    {
                        if (external[lit.Value] is Record.TypeRecord trec)
                        {
                            return(new Record.InternalDataType(trec));
                        }
                        else if (external[lit.Value] is Record.FunctionRecord frec)
                        {
                            return(new Record.InternalFunctionType(frec));
                        }
                        else
                        {
                            return(((Record.DataRecord)external[lit.Value]).Definition);
                        }
                    }

                    if (this.BaselineScope.Registry.ContainsKey(lit.Value))
                    {
                        if (this.BaselineScope.Registry[lit.Value] is Record.TypeRecord trec)
                        {
                            return(new Record.InternalDataType(trec));
                        }
                        else if (this.BaselineScope.Registry[lit.Value] is Record.FunctionRecord frec)
                        {
                            return(new Record.InternalFunctionType(frec));
                        }
                        else
                        {
                            return(((Record.DataRecord) this.BaselineScope.Registry[lit.Value]).Definition);
                        }
                    }

                    foreach (var use in this.Usings)
                    {
                        if (this.BaselineScope.Registry.ContainsKey(use + "." + lit.Value))
                        {
                            if (this.BaselineScope.Registry[use + "." + lit.Value] is Record.TypeRecord trec)
                            {
                                return(new Record.InternalDataType(trec));
                            }
                            else if (this.BaselineScope.Registry[use + "." + lit.Value] is Record.FunctionRecord frec)
                            {
                                return(new Record.InternalFunctionType(frec));
                            }
                            else
                            {
                                return(((Record.DataRecord) this.BaselineScope.Registry[use + "." + lit.Value]).Definition);
                            }
                        }
                    }

                    bool existsHeading = false;
                    foreach (var item in this.BaselineScope.Registry)
                    {
                        if (item.Key.StartsWith(lit.Value + "."))
                        {
                            existsHeading = true;
                        }
                    }

                    if (existsHeading)
                    {
                        return(new Record.NullType());
                    }
                    break;
                }
            }

            if (expression is Parser.Ast.DataDeclaration decData)
            {
                return(this.TypeData);
            }

            if (expression is Parser.Ast.FunctionDeclaration funcDecl)
            {
                Record.FunctionRecord func = RegisterFunctionRecursive(funcDecl);
                func.Symbol = "<annonymous>";
                this.Objects.Add(func.Oid, func);
                return(new Record.InternalFunctionType(func));
            }

            if (expression is LazyExpression lazy)
            {
                return(this.TypeExpression);
            }

            if (expression is Matrix2DExpression seq)
            {
                if (seq.Expressions.Length > 0)
                {
                    // note that the compile-time evaluation may add to the compiled type list.
                    // all the former dependencies (including all defined and predefined types) are
                    // listed in 'typeBuilders' parameters. other combinations will be evaluated and
                    // built in the process.

                    Record.TypeRecord rec = InferExpressionType(seq.Expressions[0, 0], external, typeBuilders, compiledTypes, programBuilder);
                    PostTypeCompile(rec, typeBuilders, compiledTypes, programBuilder);

                    Interop.AnonymousClrTypeRecord clr = new Interop.AnonymousClrTypeRecord(
                        (Interop.AnonymousClrTypeRecord) this.TypeMatrix, "_temp_" + Guid.NewGuid().ToString().Replace("-", "_"),
                        InferExpressionType(seq.Expressions[0, 0], external, typeBuilders, compiledTypes, programBuilder));

                    PostTypeCompile(clr, typeBuilders, compiledTypes, programBuilder);
                    return(clr);
                }
            }

            // todo: tuple expressions

            if (expression is BlockStatement block)
            {
                var lastStatement = block.Statements[block.Statements.Count - 1];
                if (lastStatement is ReturnStatement returnStmt)
                {
                    return(InferExpressionType(returnStmt.ReturnExpression, external, typeBuilders, compiledTypes, programBuilder));
                }

                return(InferExpressionType(lastStatement, external, typeBuilders, compiledTypes, programBuilder));
            }

            // operators

            if (expression is UnaryExpression unary)
            {
                var result = InferExpressionType(unary.Operant, external, typeBuilders, compiledTypes, programBuilder);

                // operators are defined as member function of type 'result'. the index of operators
                // can be found at IOperatorStatement.cs

                string methodName = "";
                foreach (var memberFuncs in result.MemberFunctions)
                {
                    // in case that the implementation is built-in, and cannot be modified, this will be converted
                    // to a set of il-builtin operations (such as 'add' or 'substract' etc.)

                    if (memberFuncs.Value is Interop.PlaceholderRecord placeholder)
                    {
                        string identifer = unary.Operator.Method + ":o1" +
                                           ((unary.Operator.Type == OperatorType.UnaryLeft) ? "l" : "r");
                        if (memberFuncs.Key == identifer)
                        {
                            return(placeholder.ReturnType);
                        }
                    }
                    else
                    {
                        if (memberFuncs.Key == unary.Operator.Method)
                        {
                            return(memberFuncs.Value.ReturnType);
                        }
                    }
                }
            }
            else if (expression is BinaryExpression binary)
            {
                // member expression loop

                if (binary.Operator.Method == "member")
                {
                    // the left part is a instance resource locator, e.g. a defined function object, class,
                    // or local variable in its name.

                    string rightMember = "";
                    if (binary.Right is Literal literalRight)
                    {
                        rightMember = literalRight.Value;
                    }
                    else
                    {
                        this.Current.Diagnostics.AddFatal(Parser.SyntaxError.UnexpectedMemberHierarchy,
                                                          new Parser.Span(binary.Right.Tokens[0].Location.Start,
                                                                          binary.Right.Tokens.Last().Location.End));
                        return(null);
                    }

                    var  leftPart      = InferExpressionType(binary.Left, external, typeBuilders, compiledTypes, programBuilder);
                    bool alreadyParsed = false;
                    if (binary.Left is Literal leftLiteral)
                    {
                        List <string> selections = new List <string>();
                        selections.AddRange(this.Usings);
                        this.SearchHierarchy(binary, external, selections, true);
                        leftPart      = new Record.NamescopeType(selections[0]);
                        alreadyParsed = true;
                    }

                    if (leftPart is Record.InternalFunctionType func)
                    {
                        foreach (var item in this.TypeFunction.FieldSymbols)
                        {
                            if (item.Key == rightMember)
                            {
                                var selectedItem = this.Objects[item.Value];
                                if (selectedItem is Record.DataRecord data)
                                {
                                    return(data.Definition);
                                }
                                if (selectedItem is Record.TypeRecord trec)
                                {
                                    return(new Record.InternalDataType(trec));
                                }
                                if (selectedItem is Record.FunctionRecord frec)
                                {
                                    return(new Record.InternalFunctionType(frec));
                                }
                            }
                        }

                        foreach (var item in this.TypeFunction.MemberFunctions)
                        {
                            if (item.Key == rightMember)
                            {
                                return(new Record.InternalFunctionType(item.Value));
                            }
                        }
                    }
                    else if (leftPart is Record.NamescopeType nameScope)
                    {
                        var objectDesc = nameScope.NameScope;
                        if (!alreadyParsed)
                        {
                            objectDesc = nameScope.NameScope + "." + rightMember;
                        }

                        bool match = false;
                        foreach (var item in this.BaselineScope.Registry)
                        {
                            if (item.Key.StartsWith(objectDesc))
                            {
                                if (item.Key == objectDesc)
                                {
                                    if (item.Value is Record.TypeRecord trec)
                                    {
                                        return(new Record.InternalDataType(trec));
                                    }
                                    if (item.Value is Record.FunctionRecord frec)
                                    {
                                        return(new Record.InternalFunctionType(frec));
                                    }
                                    if (item.Value is Record.DataRecord data)
                                    {
                                        return(data.Definition);
                                    }
                                }

                                match = true;
                            }
                        }

                        foreach (var item in external)
                        {
                            if (item.Key.StartsWith(objectDesc))
                            {
                                if (item.Key == objectDesc)
                                {
                                    if (item.Value is Record.TypeRecord trec)
                                    {
                                        return(new Record.InternalDataType(trec));
                                    }
                                    if (item.Value is Record.FunctionRecord frec)
                                    {
                                        return(new Record.InternalFunctionType(frec));
                                    }
                                    if (item.Value is Record.DataRecord data)
                                    {
                                        return(data.Definition);
                                    }
                                }

                                match = true;
                            }
                        }

                        if (match)
                        {
                            return(new Record.NamescopeType(objectDesc));
                        }
                        else
                        {
                            this.Current.Diagnostics.AddFatal(Parser.SyntaxError.MemberNotFound,
                                                              new Parser.Span(binary.Right.Tokens[0].Location.Start,
                                                                              binary.Right.Tokens.Last().Location.End));
                            return(null);
                        }
                    }
                    else if (leftPart is Record.TypeRecord normalType)
                    {
                        foreach (var item in normalType.FieldSymbols)
                        {
                            if (item.Key == rightMember)
                            {
                                var selectedItem = this.Objects[item.Value];
                                if (selectedItem is Record.DataRecord data)
                                {
                                    return(data.Definition);
                                }
                                if (selectedItem is Record.TypeRecord)
                                {
                                    return(this.TypeData);
                                }
                                if (selectedItem is Record.FunctionRecord frec)
                                {
                                    return(new Record.InternalFunctionType(frec));
                                }
                            }
                        }

                        foreach (var item in normalType.MemberFunctions)
                        {
                            if (item.Key == rightMember)
                            {
                                return(new Record.InternalFunctionType(item.Value));
                            }
                        }
                    }

                    this.Current.Diagnostics.AddFatal(Parser.SyntaxError.MemberNotFound,
                                                      new Parser.Span(binary.Right.Tokens[0].Location.Start,
                                                                      binary.Right.Tokens.Last().Location.End));
                    return(null);
                }

                var leftType  = InferExpressionType(binary.Left, external, typeBuilders, compiledTypes, programBuilder);
                var rightType = InferExpressionType(binary.Right, external, typeBuilders, compiledTypes, programBuilder);

                // some specific operators (type logic algebra operators, and cast operators) have their return
                // types doesn't have a corresponding member functions. these operators are built-in features
                // of language itself, and cannot be customized.

                if (leftType.Symbol == "___data" && rightType.Symbol == "___data")
                {
                    return(GetDirectTypeRecord(binary));
                }

                if (binary.Operator.Method == "cast")
                {
                    if (binary.Operator.Symbol == "->")
                    {
                        return(GetDirectTypeRecord(binary.Right));
                    }
                    else if (binary.Operator.Symbol == "<-")
                    {
                        return(GetDirectTypeRecord(binary.Left));
                    }
                }

                string methodName = "";
                foreach (var memberFuncs in leftType.MemberFunctions)
                {
                    if (memberFuncs.Value is Interop.PlaceholderRecord placeholder)
                    {
                        if (leftType.IsCompatible(rightType))
                        {
                            string identifer = binary.Operator.Method + ":o2";
                            if (memberFuncs.Key == identifer)
                            {
                                return(placeholder.ReturnType);
                            }
                        }
                    }
                    else
                    {
                        if (memberFuncs.Key == binary.Operator.Method)
                        {
                            // check whether the parameters match the given input.

                            if (memberFuncs.Value.ParameterType.Count != 2)
                            {
                                break;
                            }
                            if (memberFuncs.Value.ParameterType[0].IsCompatible(leftType) &&
                                memberFuncs.Value.ParameterType[1].IsCompatible(rightType))
                            {
                                return(memberFuncs.Value.ReturnType);
                            }
                        }
                    }
                }

                foreach (var memberFuncs in rightType.MemberFunctions)
                {
                    if (memberFuncs.Value is Interop.PlaceholderRecord placeholder)
                    {
                        if (rightType.IsCompatible(leftType))
                        {
                            string identifer = binary.Operator.Method + ":o2";
                            if (memberFuncs.Key == identifer)
                            {
                                return(placeholder.ReturnType);
                            }
                        }
                    }
                    else
                    {
                        if (memberFuncs.Key == binary.Operator.Method)
                        {
                            if (memberFuncs.Value.ParameterType.Count != 2)
                            {
                                break;
                            }
                            if (memberFuncs.Value.ParameterType[0].IsCompatible(leftType) &&
                                memberFuncs.Value.ParameterType[1].IsCompatible(rightType))
                            {
                                return(memberFuncs.Value.ReturnType);
                            }
                        }
                    }
                }
            }
            else if (expression is IndexExpression index)
            {
            }

            // function calls

            else if (expression is CallExpression call)
            {
                var func = this.InferExpressionType(call.Callee, external, typeBuilders, compiledTypes, programBuilder);
                if (func is Record.InternalFunctionType intern)
                {
                    return(intern.FunctionReference.ReturnType);
                }

                // constructor methods

                // todo: to support a full-ranged data-as-object type system we may need to built-in an
                // interpreter when recognizing and evaluating the symbols. now, we only support a static
                // type system.

                else if (func.Symbol == "___data")
                {
                    return(EvalTypeExpression(call.Callee, external, typeBuilders, compiledTypes, ProgramBuilder));
                }
            }

            return(this.TypeNull);
        }