public IncompleteType(List <object> vector) { // Read the type names. List <TypeNameMember> incompletes = new List <TypeNameMember> (); foreach (object dep in vector) { TypeNameMember typeName = dep as TypeNameMember; if (typeName != null) { incompletes.Add(typeName); } else { IncompleteType inc = (IncompleteType)dep; foreach (TypeNameMember incTypeName in inc.Dependencies) { incompletes.Add(incTypeName); } } } // Create the dependencies array. deps = incompletes.ToArray(); }
public override AstNode Visit(MemberAccess node) { // Evaluate the base reference. Expression baseReference = node.GetReference(); baseReference.SetHints(node.Hints); baseReference.Accept(this); // Get the base reference type. IChelaType baseRefType = baseReference.GetNodeType(); if(baseRefType.IsConstant()) baseRefType = DeConstType(baseRefType); // Set a default coercion type. node.SetCoercionType(baseRefType); // Get the scope. Scope scope = null; bool canStatic = true; bool canNoStatic = node.HasHints(Expression.MemberHint); bool suppressVirtual = false; bool implicitThis = false; if(baseRefType.IsMetaType()) { // Read the base reference type. baseRefType = ExtractActualType(node, baseRefType); // Handle incomplete types. if(baseRefType.IsIncompleteType()) { node.SetNodeType(baseRefType); return node; } // Handle built-in types if(!baseRefType.IsStructure() && !baseRefType.IsClass() && !baseRefType.IsInterface()) { baseRefType = currentModule.GetAssociatedClass(baseRefType); if(baseRefType == null) Error(node, "expected a known type."); } scope = (Scope) baseRefType; suppressVirtual = true; // Get the current container scope. Scope contScope = currentScope; while(contScope != null && (contScope.IsPseudoScope() || contScope.IsFunction() || contScope.IsLexicalScope())) contScope = contScope.GetParentScope(); // Check if the base type is a base of me. Structure building = contScope as Structure; if(building != null) { Structure scopeBuilding = (Structure) baseRefType; if(building.IsDerivedFrom(scopeBuilding)) { canNoStatic = true; implicitThis = true; } } } else if(baseRefType.IsNamespace()) { scope = (Namespace) baseReference.GetNodeValue(); } else if(baseRefType.IsReference()) { canStatic = false; canNoStatic = true; // Get the variable referenced type. ReferenceType refType = (ReferenceType)baseRefType; IChelaType objectType = refType.GetReferencedType(); if(objectType.IsReference()) { // Set the variable type as the coercion type. node.SetCoercionType(objectType); // Dereference. refType = (ReferenceType)objectType; objectType = refType.GetReferencedType(); } else if(objectType.IsStructure()) { // Use the structure type as the coercion type. node.SetCoercionType(objectType); } else if(objectType.IsPrimitive() || objectType.IsVector() || objectType.IsPlaceHolderType()) { node.SetCoercionType(objectType); } if(objectType.IsStructure() || objectType.IsClass() || objectType.IsInterface() || objectType.IsTypeInstance()) scope = (Scope)objectType; else if(objectType.IsPlaceHolderType()) scope = new PseudoScope((PlaceHolderType)objectType); else { scope = currentModule.GetAssociatedClass(objectType); if(scope == null) Error(node, "unimplemented primitive type classes."); } } else if(baseRefType.IsStructure()) { canStatic = false; canNoStatic = true; scope = (Scope)baseRefType; } else if(baseRefType.IsPrimitive()) { canStatic = false; canNoStatic = true; scope = currentModule.GetAssociatedClass(baseRefType); if(scope == null) Error(node, "unimplemented primitive type classes."); } else if(baseRefType.IsVector()) { canStatic = false; canNoStatic = true; scope = currentModule.GetAssociatedClass(baseRefType); if(scope == null) Error(node, "unimplemented vector type classes."); } else if(baseRefType.IsPlaceHolderType()) { canStatic = false; canNoStatic = true; scope = new PseudoScope((PlaceHolderType)baseRefType); } else { Error(node, "expected reference, namespace, struct, class, primitive, vector."); } // Check vectorial swizzle. IChelaType coercionType = node.GetCoercionType(); if(coercionType.IsVector()) { VectorType vectorType = (VectorType)coercionType; int minSize = 0; int mask = 0; string fieldName = node.GetName(); if(fieldName.Length <= 4) { // It can be a vectorial swizzle bool isSwizzle = true; for(int i = 0; i < fieldName.Length; ++i) { switch(fieldName[i]) { case 'x': case 'r': case 's': mask |= 0<<(2*i); if(minSize < 1) minSize = 1; break; case 'y': case 'g': case 't': mask |= 1<<(2*i); if(minSize < 2) minSize = 2; break; case 'z': case 'b': case 'p': mask |= 2<<(2*i); if(minSize < 3) minSize = 3; break; case 'w': case 'a': case 'q': mask |= 3<<(2*i); if(minSize < 4) minSize = 4; break; default: i = fieldName.Length + 1; isSwizzle = false; break; } } // Swizzle found. if(isSwizzle) { // Check the validity. if(minSize > vectorType.GetNumComponents()) Error(node, "accessing inexistent elements in the vector."); // Store the base variable. Variable baseVar = baseReference.GetNodeValue() as Variable; // Return the swizzle. IChelaType swizzleType = VectorType.Create(vectorType.GetPrimitiveType(), fieldName.Length); SwizzleVariable swizzleVar = new SwizzleVariable(swizzleType, baseVar, (byte)mask, fieldName.Length); node.SetNodeValue(swizzleVar); node.SetNodeType(ReferenceType.Create(swizzleType)); return node; } } } // Find the scope member. ScopeMember member = scope.FindMemberRecursive(node.GetName()); if(member == null) { // Check attribute name. if(node.IsAttributeName()) member = scope.FindMemberRecursive(node.GetName() + "Attribute"); if(member == null) Error(node, "couldn't find member '" + node.GetName() + "' in '" + scope.GetFullName() + "'."); } // Check the accesiblity. CheckMemberVisibility(node, member); // Return it. IChelaType type = null; if(member.IsNamespace()) { type = ChelaType.GetNamespaceType(); } else if(member.IsType()) { type = MetaType.Create((IChelaType)member); } else if(member.IsTypeName()) { // Read the type name. TypeNameMember typeName = (TypeNameMember)member; type = typeName.GetActualType(); // Create an incomplete type if necessary. if(type == null) type = new IncompleteType(typeName); type = MetaType.Create(type); } else if(member.IsFunctionGroup()) { FunctionGroup fgroup = (FunctionGroup)member; FunctionGroupSelector selector = new FunctionGroupSelector(fgroup); selector.SuppressVirtual = suppressVirtual; selector.ImplicitThis = implicitThis; member = selector; if(canNoStatic && canStatic) type = ChelaType.GetAnyFunctionGroupType(); else if(canStatic) type = ChelaType.GetStaticFunctionGroupType(); else type = ChelaType.GetFunctionGroupType(); } else if(member.IsFunction()) { Function function = (Function)member; type = function.GetFunctionType(); // Check the static flag. if(!canNoStatic && (function.GetFlags() & MemberFlags.InstanceMask) != MemberFlags.Static) { Error(node, "expected a static function."); } else if(function.IsMethod()) { Method method = (Method)function; node.SetSlot(method.GetVSlot()); } } else { Variable variable = (Variable)member; IChelaType variableType = variable.GetVariableType(); if(variableType.IsPassedByReference()) variableType = ReferenceType.Create(variableType); // Required for nested access. type = ReferenceType.Create(variableType); // Check the static flag. if(!canNoStatic && !variable.IsStatic()) { Error(node, "expected a static variable."); } else if(variable.IsField()) { // Use the slot. FieldVariable field = (FieldVariable) variable; node.SetSlot(field.GetSlot()); } else if(variable.IsProperty() && !variable.IsStatic() && suppressVirtual) { // Wrap the property in a direct property slot. member = new DirectPropertySlot((PropertyVariable)variable); } // Store the implicit this property. if(!variable.IsStatic()) node.ImplicitSelf = implicitThis; } // Set the value. node.SetNodeValue(member); // Set the type. node.SetNodeType(type); return node; }
public override AstNode Visit(VariableReference node) { Scope scope = currentScope; IEnumerator<Scope> iterator = scopeStack.GetEnumerator(); ScopeMember value = null; string attrName = null; bool typeHint = node.HasHints(Expression.TypeHint); bool isTypeGroup = false; bool isFunctionGroup = false; bool isNamespaceLevel = false; int mergedLevels = 0; while(scope != null) { // Find the variable in the scope. ScopeMember newValue = scope.FindMemberRecursive(node.GetName()); bool validValue = CheckTypeHint(newValue, typeHint); // Check the attribute name. if(newValue == null && node.IsAttributeName()) { if(attrName == null) attrName = node.GetName() + "Attribute"; newValue = scope.FindMemberRecursive(attrName); validValue = CheckTypeHint(newValue, typeHint); } // Use the value. if(validValue) { // If the first value its a type group, begin merging. if(value == null) { value = newValue; isTypeGroup = value.IsTypeGroup(); isFunctionGroup = value.IsFunctionGroup(); // If not merging, found the member. if(!isTypeGroup && !isFunctionGroup) break; } // Check if its a namespace level isNamespaceLevel = isNamespaceLevel || scope.IsPseudoScope(); // Found the next level. if(isTypeGroup && newValue.IsTypeGroup()) { TypeGroup typeGroup = (TypeGroup)value; TypeGroup newGroup = (TypeGroup)newValue; // Create the merged type group. if(mergedLevels == 0) value = typeGroup.CreateMerged(newGroup, isNamespaceLevel); else typeGroup.AppendLevel(newGroup, isNamespaceLevel); } else if(isFunctionGroup && newValue.IsFunctionGroup()) { FunctionGroup functionGroup = (FunctionGroup)value; FunctionGroup newGroup = (FunctionGroup)newValue; // Create the merged function group. if(mergedLevels == 0) value = functionGroup.CreateMerged(newGroup, isNamespaceLevel); else functionGroup.AppendLevel(newGroup, isNamespaceLevel); } // Increase the level count. ++mergedLevels; } // Increase the scope. if(!iterator.MoveNext()) break; scope = iterator.Current; } // If the value couldn't be found. if(value == null) Error(node, "undeclared {0} '{1}'.", typeHint ? "type" : "variable", node.GetName()); // Check the accesiblity. CheckMemberVisibility(node, value); // Calculate the type. IChelaType type = null; if(value.IsType()) { type = MetaType.Create((IChelaType)value); } else if(value.IsNamespace()) { type = ChelaType.GetNamespaceType(); } else if(value.IsTypeName()) { // Read the type name. TypeNameMember typeName = (TypeNameMember)value; type = typeName.GetActualType(); // Create an incomplete type if necessary. if(type == null) type = new IncompleteType(typeName); type = MetaType.Create(type); } else if(value.IsVariable()) { Variable variable = (Variable)value; // Check for aliases(ref/out parameters). IChelaType varType = variable.GetVariableType(); bool isAliasVariable = false; if(varType.IsReference()) { // De-reference. ReferenceType refType = (ReferenceType)varType; IChelaType referenced = refType.GetReferencedType(); if(!referenced.IsPassedByReference() || referenced.IsReference()) { // This variable is reference. isAliasVariable = true; type = varType; node.SetAliasVariable(variable); value = new ReferencedSlot(referenced); } } if(!isAliasVariable) type = ReferenceType.Create(variable.GetVariableType()); // Special checks for field variables if(variable.IsField()) { FieldVariable field = (FieldVariable) variable; if(!field.IsStatic() && currentFunction.IsStatic()) Error(node, "cannot access no static fields without an object."); } } else if(value.IsFunction()) { Function function = (Function)value; type = function.GetFunctionType(); // Special checks for methods. if(function.IsMethod()) { Method method = (Method) function; if(!method.IsStatic() && currentFunction.IsStatic()) Error(node, "cannot access no static methods without an object."); } } else if(value.IsFunctionGroup()) { FunctionGroup fgroup = (FunctionGroup)value; value = new FunctionGroupSelector(fgroup); type = ChelaType.GetStaticFunctionGroupType(); // Check for implicit this. if(!currentFunction.IsStatic()) { Structure groupScope = fgroup.GetParentScope() as Structure; Structure myScope = currentFunction.GetParentScope() as Structure; if(groupScope != null && myScope != null && (groupScope == myScope || myScope.IsDerivedFrom(groupScope))) type = ChelaType.GetAnyFunctionGroupType(); } } else Error(node, "unexpected member type."); // Set the value. node.SetNodeValue(value); // Set the node type. node.SetNodeType(type); return node; }