public override AstNode Visit(FixedVariableDecl node) { // Begin the node. builder.BeginNode(node); // Get the fixed local. LocalVariable local = node.GetVariable(); // Get the value expression. Expression valueExpr = node.GetValueExpression(); valueExpr.Accept(this); // Get the associated types. IChelaType type = node.GetNodeType(); IChelaType coercionType = node.GetCoercionType(); IChelaType valueType = valueExpr.GetNodeType(); // Perform coercion. if(valueType != coercionType ) Cast(node, valueExpr.GetNodeValue(), valueType, coercionType); // Pin references, cast pointers. if(coercionType.IsPointer()) { // Cast the pointer. if(coercionType != type) Cast(node, null, coercionType, type); // Store the pointer in a local. builder.CreateStoreLocal(local); } else { // References. valueType = DeReferenceType(coercionType); // Give a null value for null references. builder.CreateDup1(); // Create the blocks for the comparison BasicBlock notNullBlock = CreateBasicBlock(); notNullBlock.SetName("notNull"); BasicBlock nullBlock = CreateBasicBlock(); nullBlock.SetName("null"); BasicBlock nullMerge = CreateBasicBlock(); nullMerge.SetName("nullMerge"); // Compare to null. builder.CreateLoadNull(); builder.CreateCmpEQ(); builder.CreateBr(nullBlock, notNullBlock); // Set the null block content. builder.SetBlock(nullBlock); builder.CreatePop(); builder.CreateLoadNull(); builder.CreateStoreLocal(local); builder.CreateJmp(nullMerge); // Set the not null content. builder.SetBlock(notNullBlock); // Use the first element of the array. if(valueType.IsArray()) { ArrayType array = (ArrayType)valueType; for(int i = 0; i < array.GetDimensions(); ++i) builder.CreateLoadUInt8(0); builder.CreateLoadArraySlotAddr(array); // Cast the result. IChelaType slotType = PointerType.Create(array.GetValueType()); if(slotType != type) Cast(node, null, slotType, type); } else Error(node, "unsupported fixed object of type {0}.", valueType.GetName()); // Store the value. builder.CreateStoreLocal(local); // Merge the results. builder.CreateJmp(nullMerge); builder.SetBlock(nullMerge); } // End. return builder.EndNode(); }
public override AstNode Visit(FixedVariableDecl node) { // Get the variable type. IChelaType type = node.GetNodeType(); // Create the variable. LocalVariable fixedVar = new LocalVariable(node.GetName(), (LexicalScope)currentScope, type); node.SetVariable(fixedVar); // Visit the value expression. Expression valueExpr = node.GetValueExpression(); valueExpr.Accept(this); // Get the value type. IChelaType valueType = valueExpr.GetNodeType(); // The value must be a reference or a pointer. if(!valueType.IsReference() && !valueType.IsPointer()) Error(valueExpr, "the value expression must be a reference or a pointer."); if(valueType.IsPointer()) { if(Coerce(node, type, valueType, valueExpr.GetNodeValue()) != type) Error(valueExpr, "cannot convert {0} into {1}.", valueType.GetName(), type.GetName()); // Coerce the value. node.SetCoercionType(type); } else { // Remove references. IChelaType refType = DeReferenceType(valueType); if(refType.IsReference()) refType = DeReferenceType(refType); // Only support arrays if(refType.IsArray()) { ArrayType array = (ArrayType)refType; IChelaType pointerType = PointerType.Create(array.GetValueType()); if(Coerce(node, type, pointerType, null) != type) Error(valueExpr, "cannot convert {0} into {1}.", pointerType.GetName(), type.GetName()); } // Set the new coercion type. node.SetCoercionType(ReferenceType.Create(refType)); } return node; }