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)); }
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); } }
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); }
public override string GetIdentifer(TypeRecord caller, AnalysisEnvironment environment) { this.Identifer = "any"; this.ClrTypeRecordIndex = -3; return("any"); }
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 + ">"); }
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); }
public InternalDataType(TypeRecord record) { this.Type = record; }
public ExcludeType(TypeRecord target, TypeRecord exclusion) : this() { this.Target = target; this.Exclusion = exclusion; }
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); }