private void GenerateOutputs(ZMethod zMethod, Class outputsClass)
{
List<Field> outputs = new List<Field>(10);
Method outputsGetValue = (Method)Templates.GetMemberByName(outputsClass.Members, "GetValue");
Method outputsSetValue = (Method)Templates.GetMemberByName(outputsClass.Members, "SetValue");
System.Compiler.Switch switchOutputsGetValue =
(System.Compiler.Switch)Templates.GetStatementTemplate("GetFieldInfoSwitch");
outputsGetValue.Body.Statements.Add(switchOutputsGetValue);
System.Compiler.Switch switchOutputsSetValue =
(System.Compiler.Switch)Templates.GetStatementTemplate("SetFieldInfoSwitch");
outputsSetValue.Body.Statements.Add(switchOutputsSetValue);
Method copier = (Method)Templates.GetMemberByName(outputsClass.Members, "CopyContents");
// Create fields in Inputs or Outputs for the parameters
for (int i = 0, n = zMethod.Parameters.Count; i < n; i++)
{
Parameter param = zMethod.Parameters[i];
if (param == null || param.Type == null || (param.Flags & ParameterFlags.Out) == 0)
continue;
TypeNode zingType = param.Type;
zingType = ((Reference)zingType).ElementType;
Field f = new Field(outputsClass, null, FieldFlags.Public,
new Identifier("priv_" + param.Name.Name),
param.Type, null);
if (f.Type is Reference)
f.Type = ((Reference)f.Type).ElementType;
if (GetTypeClassification(f.Type) == TypeClassification.Heap)
{
f.Type = this.ZingPtrType;
}
else if (!IsPredefinedType(f.Type))
f.Type = new TypeExpression(new QualifiedIdentifier(
new Identifier("Application"), zingType.Name), zingType.SourceContext);
Identifier idFieldName = new Identifier("id_" + param.Name.Name);
Field idf = new Field(outputsClass, null, FieldFlags.Public | FieldFlags.Static,
idFieldName,
SystemTypes.Int32, null);
idf.Initializer = new Literal(i, SystemTypes.Int32);
SwitchCase getCase = ((System.Compiler.Switch)Templates.GetStatementTemplate("GetFieldInfoCase")).Cases[0];
Replacer.Replace(getCase, "_fieldId", new Literal(i, SystemTypes.Int32));
Replacer.Replace(getCase, "_fieldName", new Identifier(f.Name.Name));
switchOutputsGetValue.Cases.Add(getCase);
SwitchCase setCase = ((System.Compiler.Switch)Templates.GetStatementTemplate("SetFieldInfoCase")).Cases[0];
Replacer.Replace(setCase, "_fieldId", new Literal(i, SystemTypes.Int32));
Replacer.Replace(setCase, "_fieldName", new Identifier(f.Name.Name));
TypeExpression tn = f.Type as TypeExpression;
Replacer.Replace(setCase, "_fieldType", tn != null ? tn.Expression : new Identifier(f.Type.Name.Name));
switchOutputsSetValue.Cases.Add(setCase);
QualifiedIdentifier localInputOrOutput = new QualifiedIdentifier(new Identifier("LocType"), new Identifier("Output"));
Property accessor = GetAccessorProperty("outputAccessor", f.Type, param.Name, f.Name, idf.Name, localInputOrOutput);
outputsClass.Members.Add(f);
outputsClass.Members.Add(idf);
outputsClass.Members.Add(accessor);
f.DeclaringType = outputsClass;
idf.DeclaringType = outputsClass;
accessor.DeclaringType = outputsClass;
if (accessor.Getter != null)
{
outputsClass.Members.Add(accessor.Getter);
accessor.Getter.DeclaringType = outputsClass;
}
if (accessor.Setter != null)
{
outputsClass.Members.Add(accessor.Setter);
accessor.Setter.DeclaringType = outputsClass;
}
//for outputs create an additional lastfunction accessor
QualifiedIdentifier lfcOutput =
new QualifiedIdentifier(new Identifier("LocType"), new Identifier("LastFunctionOutput"));
Identifier lfcid = new Identifier("_Lfc_" + param.Name.Name);
Property lfcAccessor = GetAccessorProperty("lastFunctionOutputAccessor", f.Type,
lfcid, f.Name, idf.Name, lfcOutput);
outputsClass.Members.Add(lfcAccessor);
lfcAccessor.DeclaringType = outputsClass;
if (lfcAccessor.Getter != null)
{
outputsClass.Members.Add(lfcAccessor.Getter);
lfcAccessor.Getter.DeclaringType = outputsClass;
}
if (zingType is Struct && !zingType.IsPrimitive && f.Type != SystemTypes.Decimal)
collectStructAccessors(false, (Struct)zingType, f.Name,
param.Name.Name, outputsClass);
copier.Body.Statements.Add(GetCopyStatement(f.Name));
outputs.Add(f);
}
if (zMethod.ReturnType.TypeCode != TypeCode.Empty)
{
Field f = new Field(outputsClass, null, FieldFlags.Public,
new Identifier("priv_ReturnValue"),
zMethod.ReturnType, null);
QualifiedIdentifier localInputOrOutput = new QualifiedIdentifier(new Identifier("LocType"), new Identifier("Output"));
TypeNode zingType = zMethod.ReturnType;
if (GetTypeClassification(f.Type) == TypeClassification.Heap)
{
f.Type = this.ZingPtrType;
}
else if (!IsPredefinedType(f.Type))
{
f.Type = new TypeExpression(new QualifiedIdentifier(
new Identifier("Application"), zingType.Name), zingType.SourceContext);
}
Identifier idFieldName = new Identifier("id_ReturnValue");
Field idf = new Field(outputsClass, null, FieldFlags.Public | FieldFlags.Static,
idFieldName,
SystemTypes.Int32, null);
idf.Initializer = new Literal(zMethod.Parameters.Count, SystemTypes.Int32);
SwitchCase getCase = ((System.Compiler.Switch)Templates.GetStatementTemplate("GetFieldInfoCase")).Cases[0];
Replacer.Replace(getCase, "_fieldId", new Literal(zMethod.Parameters.Count, SystemTypes.Int32));
Replacer.Replace(getCase, "_fieldName", new Identifier("priv_ReturnValue"));
switchOutputsGetValue.Cases.Add(getCase);
SwitchCase setCase = ((System.Compiler.Switch)Templates.GetStatementTemplate("SetFieldInfoCase")).Cases[0];
Replacer.Replace(setCase, "_fieldId", new Literal(zMethod.Parameters.Count, SystemTypes.Int32));
Replacer.Replace(setCase, "_fieldName", new Identifier("priv_ReturnValue"));
TypeExpression tn = f.Type as TypeExpression;
Replacer.Replace(setCase, "_fieldType", tn != null ? tn.Expression : new Identifier(f.Type.Name.Name));
switchOutputsSetValue.Cases.Add(setCase);
Property accessor = GetAccessorProperty("outputAccessor", f.Type,
new Identifier("_ReturnValue"),
f.Name, idf.Name, localInputOrOutput);
QualifiedIdentifier lfcOutput = new QualifiedIdentifier(new Identifier("LocType"), new Identifier("LastFunctionOutput"));
Property lfcAccessor = GetAccessorProperty("lastFunctionOutputAccessor", f.Type,
new Identifier("_Lfc_ReturnValue"),
f.Name, idf.Name, lfcOutput);
Identifier qualifier = new Identifier("outputs");
outputsClass.Members.Add(f);
outputsClass.Members.Add(idf);
outputsClass.Members.Add(accessor);
outputsClass.Members.Add(lfcAccessor);
f.DeclaringType = outputsClass;
idf.DeclaringType = outputsClass;
accessor.DeclaringType = outputsClass;
lfcAccessor.DeclaringType = outputsClass;
if (accessor.Getter != null)
{
outputsClass.Members.Add(accessor.Getter);
accessor.Getter.DeclaringType = outputsClass;
}
if (accessor.Setter != null)
{
outputsClass.Members.Add(accessor.Setter);
accessor.Setter.DeclaringType = outputsClass;
}
if (lfcAccessor.Getter != null)
{
outputsClass.Members.Add(lfcAccessor.Getter);
lfcAccessor.Getter.DeclaringType = outputsClass;
}
if (zingType is Struct && !zingType.IsPrimitive && f.Type != SystemTypes.Decimal)
{
collectStructAccessors(false, (Struct)zingType, f.Name,
"_ReturnValue", outputsClass);
collectStructAccessors(false, (Struct)zingType, f.Name,
"_Lfc_ReturnValue", outputsClass);
}
copier.Body.Statements.Add(GetCopyStatement(f.Name));
outputs.Add(f);
}
Method writer = (Method)Templates.GetMemberByName(outputsClass.Members, "WriteString");
Method traverser = (Method)Templates.GetMemberByName(outputsClass.Members, "TraverseFields");
for (int i = 0, n = outputs.Count; i < n; i++)
{
Field f = (Field)outputs[i];
writer.Body.Statements.Add
(GetWriterStatement("this", f.Type, f.Name));
traverser.Body.Statements.Add(GetTraverserStatement("this", f.Type, f.Name));
}
}