File [Ivy]<Nelson>Lupine>LupineMarshalTypeConstructorImpl.mesa.
Last edited by BZM on March 18, 1982 11:18 AM.
This module cooperates with LupineMarshal*Impl to export LupineMarshal.
Last Edited by: Birrell, September 8, 1983 4:38 pm
DIRECTORY
IO USING [PutFR],
LupineDeclare USING [WriteSymbolName, WriteTypeName],
LupineManagerPrivate USING [
Indent,
Nest, ParamPassingMethod, String, StringNIL,
WFS, WFS1, WFSL, WFL, WFL1, WFLL ],
LupineMarshal USING [FieldInfo, ParamInfo, ParamRecordKind],
LupineMarshalPrivate USING [
ContainsRefs, ContainsSequences, ContainsStatics,
CopyOne, CopyTwo, CopyType, Direction, Error, HasEmptyIndex,
MarshalInfo, MarshalType, MaxPointerDepth,
NeedsMarshaling, NeedsOperationProc, OperationProc,
ParentInfo, Passing,
SubStrings, UniqueName, VerifyPassingMethods, WriteNEW ],
LupineSymbolTable USING [
ComponentProcedure, EnumerateRecord,
EnumerateVariants, GetTypeInfo, IsAnonymous,
SymbolHandle, SymbolName,
TypeHandle, TypeInfo, Types, VariantProcedure ],
Rope USING [Cat];
LupineMarshalTypeConstructorImpl: PROGRAM
IMPORTS
IO, Declare: LupineDeclare, LupineManagerPrivate,
Private: LupineMarshalPrivate, ST: LupineSymbolTable, Rope
EXPORTS LupineMarshalPrivate
= BEGIN OPEN LupineManagerPrivate, LupineMarshal;
Types from the internal LupineManagerPrivate interface.
ParentInfo: TYPE = Private.ParentInfo;
MarshalInfo: TYPE = Private.MarshalInfo;
NeedsOperationProc: TYPE = Private.NeedsOperationProc;
OperationProc: TYPE = Private.OperationProc;
SubStrings: TYPE = Private.SubStrings;
Marshaling routines for type constructors (i.e., nonbuiltin types).
MarshalTransfer: PUBLIC PROCEDURE [
name: String,
transferInfo: Transfer ST.TypeInfo,
parentInfo: ParentInfo,
marshalInfo: MarshalInfo,
nest: Nest ] =
BEGIN
Private.VerifyPassingMethods[value: TRUE, handle: TRUE, marshalInfo: marshalInfo];
Private.Error[code: TransferParameter, type: transferInfo.self];
END;
MarshalRecord: PUBLIC PROCEDURE [
name: String,
recInfo: Record ST.TypeInfo,
parentInfo: ParentInfo,
marshalInfo: MarshalInfo,
nest: Nest ] =
BEGIN
Private.VerifyPassingMethods[value: TRUE, marshalInfo: marshalInfo];
IF recInfo.hasSequences
THEN MarshalSequenceRecord[ nest: nest,
recName: name, recInfo: recInfo,
parentInfo: parentInfo, marshalInfo: marshalInfo ]
ELSE MarshalFixedRecord[ nest: nest,
recName: name, recInfo: recInfo,
parentInfo: parentInfo, marshalInfo: marshalInfo ];
END;
MarshalFixedRecord: PROCEDURE [
recName: String,
recInfo: Record ST.TypeInfo,
parentInfo: ParentInfo,
marshalInfo: MarshalInfo,
nest: Nest ] =
BEGIN
MarshalFixedRecord needs storage for the record to already be allocated.
Thus, sequence containing records are separately handled by
MarshalSequenceRecord, which calls us to do some work.
IF (SELECT parentInfo.typeInfo.type FROM
Record, VariantPart => FALSE, ENDCASE => TRUE)
AND Private.ContainsStatics[recInfo.self]
THEN BEGIN
Private.CopyType[ nest: nest,
variableName: recName, variableInfo: recInfo,
parentInfo: parentInfo, marshalInfo: marshalInfo ];
After a blind copy, always reset any Refs to NIL immediately.
This consistency-making must be done atomically, ie, there
must be no possibility of a fault (UNWIND) between the copying
and the NIL-making.
MakeRefsNil[ nest: nest,
name: recName,
type: recInfo.self,
parentInfo: parentInfo,
marshalInfo: marshalInfo ];
END;
DoRecordOperation[ nest: nest,
opProc: Private.MarshalType, needsOpProc: Private.NeedsMarshaling,
recName: recName, recInfo: recInfo,
marshalInfo: marshalInfo ];
END;
MarshalSequenceRecord: PROCEDURE [
recName: String,
recInfo: Record ST.TypeInfo,
parentInfo: ParentInfo,
marshalInfo: MarshalInfo,
nest: Nest ] =
BEGIN
IF ~recInfo.hasSequences OR
(SELECT parentInfo.typeInfo.type FROM
Pointer, Ref => FALSE, ENDCASE => TRUE)
THEN ERROR;
SELECT marshalInfo.direction FROM
toPkt =>
BEGIN
Private.CopyOne[ nest: nest,
wordsNeeded: 3,
value: [parentInfo.name, "=NIL"--L--],
marshalInfo: marshalInfo ];
WFL[nest, "IF "--L--, parentInfo.name, " # NIL THEN BEGIN"--L--];
WFL1[nest+1, "-- Record has a sequence, put its length up front."--L--];
Private.CopyTwo[ nest: nest+1,
wordsNeeded: 0,
value: SubStrings["LENGTH[DESCRIPTOR["--L--, recName, "]]"--L--],
marshalInfo: marshalInfo ];
IF Private.Passing[Result, argument, marshalInfo]
THEN WFL1[nest+1, "NULL; -- Call by result, don't send record."--L--]
ELSE MarshalFixedRecord[ nest: nest+1,
recName: recName, recInfo: recInfo,
parentInfo: parentInfo, marshalInfo: marshalInfo ];
WFL[nest+1, "END; -- IF "--L--, parentInfo.name, " # NIL."--L--];
END;
fromPkt =>
BEGIN
WFL1[nest, "recordIsNIL: Lupine.NilHeader;"--L--];
Private.CopyOne[ nest: nest,
wordsNeeded: 3,
value: ["recordIsNIL"--L--],
marshalInfo: marshalInfo ];
IF Private.Passing[Result, result, marshalInfo]
OR Private.Passing[Var, result, marshalInfo]
THEN WFL[nest,
"IF recordIsNIL # ("--L--, parentInfo.name,
"=NIL) THEN Lupine.UnmarshalingError;"--L--];
WFL1[nest, "IF recordIsNIL"--L--];
WFL[nest+1, "THEN "--L--, parentInfo.name, " ← NIL"--L--];
WFL1[nest+1, "ELSE BEGIN"--L--];
WFL1[nest+2, "seqLength: Lupine.SequenceHeader;"--L--];
Private.CopyTwo[ nest: nest+2,
wordsNeeded: 0,
value: ["seqLength"--L--],
marshalInfo: marshalInfo ];
IF Private.Passing[Result, result, marshalInfo]
OR Private.Passing[Var, result, marshalInfo]
THEN BEGIN
WFL[nest+2,
"IF seqLength # LENGTH[DESCRIPTOR["--L--, recName,
"]] THEN Lupine.UnmarshalingError;"--L-- ];
WFL1[nest+2,
"NULL; -- Call by var or result, use existing record."--L--];
END
ELSE BEGIN
WFS[Indent[nest+2], parentInfo.name, " ← ("--L--];
Private.WriteNEW[
ptrInfo: parentInfo.typeInfo, marshalInfo: marshalInfo ];
WFS1["["--L--];
Declare.WriteTypeName[recInfo.self];
WFS1["[Lupine.SHORT[seqLength]]]);\n"--L--];
END;
IF Private.Passing[Result, argument, marshalInfo]
THEN WFL1[nest+2,
"NULL; -- Call by result, use uninitialized record."--L--]
ELSE MarshalFixedRecord[ nest: nest+2,
recName: recName, recInfo: recInfo,
parentInfo: parentInfo, marshalInfo: marshalInfo ];
WFL[nest+2, "END; -- IF recordIsNIL."--L--];
END;
ENDCASE => ERROR;
END;
DoRecordOperation: PROCEDURE [
opProc: OperationProc,
needsOpProc: NeedsOperationProc,
recName: String,
recInfo: Record ST.TypeInfo,
marshalInfo: MarshalInfo,
nest: Nest ] =
BEGIN
MarshalField: ST.ComponentProcedure =
BEGIN
IF ~needsOpProc[componentType] THEN RETURN;
Monitored records will be caught because of the LOCK field.
opProc[ nest: nest,
name: FieldName[
fieldSymbol: component,
recordType: recInfo.self,
anonOk: -- Single component variant records don't need names.
componentIndex = 1 AND
recInfo.hasVariants AND
ST.GetTypeInfo[componentType].type = VariantPart ],
type: componentType,
parentInfo: [recName, recInfo],
marshalInfo: marshalInfo ];
END;
IF needsOpProc[recInfo.self] THEN BEGIN
WFL[nest, "BEGIN OPEN record: "--L--, recName, ";"--L--];
[] ← ST.EnumerateRecord[recordType: recInfo.self, proc: MarshalField];
WFL[nest, "END; -- OPEN record: "--L--, recName, "."--L--];
END;
END;
MarshalVariantPart: PUBLIC PROCEDURE [
name: String,
varInfo: VariantPart ST.TypeInfo,
parentInfo: ParentInfo,
marshalInfo: MarshalInfo,
nest: Nest ] =
BEGIN
Private.VerifyPassingMethods[value: TRUE, marshalInfo: marshalInfo];
IF Private.ContainsSequences[varInfo.self]
THEN Private.Error[code: SequenceInsideVariant, type: varInfo.self]
ELSE DoVariantOperation[ nest: nest,
opProc: Private.MarshalType, needsOpProc: Private.NeedsMarshaling,
varName: name, varInfo: varInfo,
marshalInfo: marshalInfo ];
END;
DoVariantOperation: PROCEDURE [
opProc: OperationProc,
needsOpProc: NeedsOperationProc,
varName: String,
varInfo: VariantPart ST.TypeInfo,
marshalInfo: MarshalInfo,
nest: Nest ] =
BEGIN
MarshalVariant: ST.VariantProcedure =
BEGIN
IF ~needsOpProc[variantRecordType] THEN RETURN;
WFS1[Indent[nest+1]];
Declare.WriteSymbolName[variantTag];
WFS1[" =>\n"--L--];
opProc[ nest: nest+2,
name: "variant"--L--,
type: variantRecordType,
parentInfo: [varName, varInfo],
marshalInfo: marshalInfo ];
END; -- MarshalVariant.
SELECT TRUE FROM
~needsOpProc[varInfo.self] => NULL;
varInfo.kind = Computed =>
Private.Error[code: ComputedVariant, type: varInfo.self];
ENDCASE =>
BEGIN
WFL1[nest, "WITH variant: record SELECT FROM"--L--];
[] ← ST.EnumerateVariants[
variantPartType: varInfo.self, proc: MarshalVariant];
WFL1[nest+1, "ENDCASE => NULL; -- WITH variant: record."--L--];
END;
END;
MarshalPointer: PUBLIC PROCEDURE [
name: String,
pointerInfo: Pointer ST.TypeInfo,
parentInfo: ParentInfo,
marshalInfo: MarshalInfo,
nest: Nest ] =
BEGIN
MarshalPointerTypes[ nest: nest,
ptrName: name, ptrInfo: pointerInfo,
referentType: pointerInfo.referentType,
parentInfo: parentInfo, marshalInfo: marshalInfo ];
END;
MarshalRef: PUBLIC PROCEDURE [
name: String,
refInfo: Ref ST.TypeInfo,
parentInfo: ParentInfo,
marshalInfo: MarshalInfo,
nest: Nest ] =
BEGIN
MarshalPointerTypes[ nest: nest,
ptrName: name, ptrInfo: refInfo,
referentType: refInfo.referentType,
parentInfo: parentInfo, marshalInfo: marshalInfo ];
END;
MarshalPointerTypes: PROCEDURE [
ptrName: String,
ptrInfo: ST.TypeInfo,
referentType: ST.TypeHandle,
parentInfo: ParentInfo,
marshalInfo: MarshalInfo,
nest: Nest ] =
BEGIN
referentInfo: ST.TypeInfo = ST.GetTypeInfo[referentType];
referentName: String = ptrName.Cat["^"];
Private.VerifyPassingMethods[all: TRUE, marshalInfo: marshalInfo];
marshalInfo.ptrDepth ← marshalInfo.ptrDepth + 1;
SELECT TRUE FROM
marshalInfo.ptrDepth > Private.MaxPointerDepth =>
Private.Error[code: ProbablePointerRecursion, type: ptrInfo.self];
(WITH refInfo: referentInfo SELECT FROM
Basic => SELECT refInfo.kind FROM
Unspecified, Other => TRUE, ENDCASE => FALSE,
Any => TRUE,
Opaque => ~refInfo.lengthKnown,
ENDCASE => FALSE) =>
Private.Error[code: InvalidHandle, type: ptrInfo.self];
(WITH refInfo: referentInfo SELECT FROM
Text, StringBody => TRUE,
Record => refInfo.hasSequences,
ENDCASE => FALSE) =>
Private.MarshalType[ nest: nest,
name: referentName,
type: referentType,
parentInfo: [ptrName, ptrInfo],
marshalInfo: marshalInfo ];
ENDCASE =>
MarshalFixedReferent[ nest: nest,
ptrName: ptrName, ptrInfo: ptrInfo,
referentName: referentName, referentInfo: referentInfo,
parentInfo: parentInfo, marshalInfo: marshalInfo ];
marshalInfo.ptrDepth ← marshalInfo.ptrDepth - 1;
END;
MarshalFixedReferent: PROCEDURE [
ptrName: String, ptrInfo: ST.TypeInfo,
referentName: String, referentInfo: ST.TypeInfo,
parentInfo: ParentInfo,
marshalInfo: MarshalInfo,
nest: Nest ] =
BEGIN
This routine expects that the referentType has a fixed,
nondynamic length. MarshalPointerTypes should have screened this.
SELECT marshalInfo.direction FROM
toPkt =>
BEGIN
Private.CopyOne[ nest: nest,
wordsNeeded: 1,
value: [ptrName, "=NIL"--L--],
marshalInfo: marshalInfo ];
WFL[nest, "IF "--L--, ptrName, " # NIL THEN"--L--];
IF Private.Passing[Result, argument, marshalInfo]
THEN WFL1[nest+1, "NULL; -- Call by result, send nothing."--L--]
ELSE Private.MarshalType[ nest: nest+1,
name: referentName, type: referentInfo.self,
parentInfo: [ptrName, ptrInfo], marshalInfo: marshalInfo ];
END;
fromPkt =>
BEGIN
WFL1[nest, "isNIL: Lupine.NilHeader;"--L--];
Private.CopyOne[ nest: nest,
wordsNeeded: 1,
value: ["isNIL"--L--],
marshalInfo: marshalInfo ];
IF Private.Passing[Result, result, marshalInfo] OR
Private.Passing[Var,result,marshalInfo]
THEN BEGIN
WFL[nest,
"IF isNIL # ("--L--, ptrName,
"=NIL) THEN Lupine.UnmarshalingError;"--L--];
WFL1[nest, "IF ~isNIL THEN"--L--];
WFL1[nest+1, "-- Call by var or result, use existing referent."--L--];
Private.MarshalType[ nest: nest+1,
name: referentName, type: referentInfo.self,
parentInfo: [ptrName, ptrInfo], marshalInfo: marshalInfo ];
END
ELSE BEGIN
WFL1[nest, "IF isNIL"--L--];
WFL[nest+1, "THEN "--L--, ptrName, " ← NIL"--L--];
WFL1[nest+1, "ELSE BEGIN"--L--];
WFS[Indent[nest+2], ptrName, " ← ("--L--];
Private.WriteNEW[ptrInfo: ptrInfo, marshalInfo: marshalInfo];
WFS1["["--L--];
Declare.WriteTypeName[referentInfo.self];
WFS1["]);\n"--L--];
IF Private.Passing[Result, argument, marshalInfo]
THEN WFL1[nest+2,
"NULL; -- Call by result, use uninitialized referent."--L--]
ELSE Private.MarshalType[ nest: nest+2,
name: referentName, type: referentInfo.self,
parentInfo: [ptrName, ptrInfo], marshalInfo: marshalInfo ];
WFL1[nest+2, "END; -- IF isNIL."--L--];
END;
END;
ENDCASE => ERROR;
END;
MarshalList: PUBLIC PROCEDURE [
name: String,
listInfo: List ST.TypeInfo,
parentInfo: ParentInfo,
marshalInfo: MarshalInfo,
nest: Nest ] =
BEGIN
Private.VerifyPassingMethods[value: TRUE, handle: TRUE, marshalInfo: marshalInfo];
DoListOperation[ nest: nest,
opProc: Private.MarshalType, needsOpProc: Private.NeedsMarshaling,
listName: name, listInfo: listInfo,
marshalInfo: marshalInfo ];
END;
DoListOperation: PROCEDURE [
opProc: OperationProc,
needsOpProc: NeedsOperationProc,
listName: String,
listInfo: List ST.TypeInfo,
marshalInfo: MarshalInfo,
nest: Nest ] =
BEGIN
thisNode: String = Private.UniqueName[
root: "thisNode"--L--,
marshalInfo: marshalInfo ];
thisNodeFirst: String = Private.UniqueName[
root: "thisNode"--L--, suffix: ".first"--L--,
marshalInfo: marshalInfo ];
IF opProc # Private.MarshalType THEN ERROR;
DoListOperation does only marshaling correctly for now.
SELECT marshalInfo.direction FROM
toPkt =>
BEGIN
WFS[Indent[nest], thisNode, ": "--L--];
Declare.WriteTypeName[type: listInfo.self, includeReadonly: FALSE];
WFS1[";\n"--L--];
WFL1[nest, "listLength: Lupine.ListHeader ← 0;"--L--];
WFSL[ Indent[nest], "FOR "--L--, thisNode, " ← "--L--,
listName, ", "--L--, thisNode, ".rest UNTIL "--L--,
thisNode, " = NIL DO\n"--L--];
WFL1[nest+1, "listLength ← listLength + 1; ENDLOOP;"--L--];
Private.CopyTwo[ nest: nest,
wordsNeeded: 2,
value: SubStrings["listLength"--L--],
marshalInfo: marshalInfo ];
WFSL[ Indent[nest], "FOR "--L--, thisNode, " ← "--L--,
listName, ", "--L--, thisNode, ".rest UNTIL "--L--,
thisNode, " = NIL DO\n"--L--];
opProc[ nest: nest+1,
name: thisNodeFirst,
type: listInfo.firstType,
parentInfo: [listName, listInfo],
marshalInfo: marshalInfo ];
WFL[nest+1, "ENDLOOP; -- FOR "--L--, thisNode, "."--L--];
END;
fromPkt =>
BEGIN
lastNode: String = UniqueName[
root: "lastNode",
marshalInfo: marshalInfo ];
WFS[Indent[nest], "lastNode: "--L--];
Declare.WriteTypeName[type: listInfo.self, includeReadonly: FALSE];
WFS[" ← ("--L--, listName, " ← NIL);\n"--L--];
WFL1[nest, "listLength: Lupine.ListHeader;"--L--];
Private.CopyTwo[ nest: nest,
wordsNeeded: 2,
value: SubStrings["listLength"--L--],
marshalInfo: marshalInfo ];
WFL1[nest, "WHILE listLength > 0 DO"--L--];
WFS[Indent[nest+1], thisNode, ": "--L--];
Declare.WriteTypeName[type: listInfo.self, includeReadonly: FALSE];
WFS1[" = "--L--];
Private.WriteNEW[
allocOp: cons, ptrInfo: listInfo, marshalInfo: marshalInfo];
WFS1["[--DefaultValue--,NIL];\n"--L--];
opProc[ nest: nest+1,
name: thisNodeFirst,
type: listInfo.firstType,
parentInfo: [listName, listInfo],
marshalInfo: marshalInfo ];
WFL1[nest+1, "IF lastNode # NIL"--L--];
WFSL[
Indent[nest+2], "THEN lastNode ← (lastNode.rest ← "--L--,
thisNode, ")\n"--L--,
Indent[nest+2], "ELSE lastNode ← ("--L--, listName, " ← "--L--,
thisNode, ");\n"--L-- ];
WFL1[nest+1, "listLength ← listLength - 1;"--L--];
WFL1[nest+1, "ENDLOOP; -- WHILE listLength > 0."--L--];
END;
ENDCASE => ERROR;
END;
MarshalArray: PUBLIC PROCEDURE [
name: String,
arrayInfo: Array ST.TypeInfo,
parentInfo: ParentInfo,
marshalInfo: MarshalInfo,
nest: Nest ] =
BEGIN
Private.VerifyPassingMethods[value: TRUE, marshalInfo: marshalInfo];
IF Private.HasEmptyIndex[index: arrayInfo.indexType]
THEN Private.Error[code: EmptyArray, type: arrayInfo.self]
ELSE MarshalVector[ nest: nest,
vectorName: name, vectorInfo: arrayInfo,
indexType: arrayInfo.indexType, elementType: arrayInfo.elementType,
parentInfo: parentInfo, marshalInfo: marshalInfo ];
END;
MarshalDescriptor: PUBLIC PROCEDURE [
name: String,
descInfo: Descriptor ST.TypeInfo,
parentInfo: ParentInfo,
marshalInfo: MarshalInfo,
nest: Nest ] =
BEGIN
lengthString: String = IO.PutFR["(IF BASE[%g]=NIL THEN 0 ELSE LENGTH[%g])",
[rope[name]], [rope[name]] ];
Private.VerifyPassingMethods[all: TRUE, marshalInfo: marshalInfo];
SELECT marshalInfo.direction FROM
toPkt =>
BEGIN
Private.CopyTwo[ nest: nest,
wordsNeeded: 2,
value: [lengthString],
marshalInfo: marshalInfo ];
WFL[nest, "IF BASE["--L--, name, "] # NIL THEN"--L--];
IF Private.Passing[Result, argument, marshalInfo]
THEN WFL1[nest+1, "NULL; -- Call by result, send length only."--L--]
ELSE BEGIN
MarshalVector[ nest: nest+1,
vectorName: name, vectorInfo: descInfo,
indexType: descInfo.indexType, elementType: descInfo.elementType,
parentInfo: parentInfo, marshalInfo: marshalInfo ];
END;
END;
fromPkt =>
BEGIN
WFSL[Indent[nest],
"DescriptorType: TYPE = RECORD ["--L--,
(IF descInfo.packed THEN "PACKED "--L-- ELSE ""--L--),
"SEQUENCE COMPUTED CARDINAL OF "--L--];
Declare.WriteTypeName[descInfo.elementType];
WFS1["];\n"--L--];
WFL1[nest, "descLength: Lupine.SequenceHeader;"--L--];
Private.CopyTwo[ nest: nest,
wordsNeeded: 2,
value: ["descLength"--L--],
marshalInfo: marshalInfo];
IF Private.Passing[Result, result, marshalInfo] OR
Private.Passing[Var,result,marshalInfo]
THEN BEGIN
WFL[nest, "IF descLength # "--L--, lengthString];
WFL[nest+1, "THEN Lupine.UnmarshalingError;"--L--];
WFL1[nest,
"NULL; -- Call by var or result, use existing descriptor."--L--];
END
ELSE BEGIN
WFSL[Indent[nest], name, " ← DESCRIPTOR[\n"--L--,
Indent[nest+1], "("--L--];
Private.WriteNEW[ptrInfo: descInfo, marshalInfo: marshalInfo];
WFS["[DescriptorType[Lupine.SHORT[descLength]]]),\n"--L--,
Indent[nest+1], "Lupine.SHORT[descLength]];\n"--L--];
END;
IF Private.Passing[Result, argument, marshalInfo]
THEN WFL1[nest,
"NULL; -- Call by result, use uninitialized descriptor."--L--]
ELSE BEGIN
MarshalVector[ nest: nest,
vectorName: name, vectorInfo: descInfo,
indexType: descInfo.indexType, elementType: descInfo.elementType,
parentInfo: parentInfo, marshalInfo: marshalInfo ]
END;
END;
ENDCASE => ERROR;
END;
MarshalSequence: PUBLIC PROCEDURE [
name: String,
seqInfo: Sequence ST.TypeInfo,
parentInfo: ParentInfo,
marshalInfo: MarshalInfo,
nest: Nest ] =
BEGIN
Private.VerifyPassingMethods[value: TRUE, marshalInfo: marshalInfo];
WITH tagName: seqInfo SELECT FROM
Computed => Private.Error[code: ComputedSequence, type: seqInfo.self];
Named =>
BEGIN
WFL1[nest, "-- The sequence's length was carried by its record."--L--];
IF ~Private.NeedsMarshaling[seqInfo.elementType] THEN ERROR;
MarshalVector[ nest: nest,
vectorName: name, vectorInfo: seqInfo,
indexType: seqInfo.indexType, elementType: seqInfo.elementType,
parentInfo: parentInfo, marshalInfo: marshalInfo ];
END;
ENDCASE => ERROR;
END;
MarshalVector: PROCEDURE [
vectorName: String,
vectorInfo: ST.TypeInfo,
indexType, elementType: ST.TypeHandle,
parentInfo: ParentInfo,
marshalInfo: MarshalInfo,
nest: Nest ] =
BEGIN
MarshalVector must generate exactly one statement.
Caller guarantees that the vector has >= 0 elements in it, and that
any header information for sequences and descriptors has been sent.
IF ~Private.NeedsMarshaling[elementType]
THEN Private.CopyType[ nest: nest,
variableName: vectorName, variableInfo: vectorInfo,
parentInfo: parentInfo, marshalInfo: marshalInfo ]
ELSE DoVectorOperation[ nest: nest,
opProc: Private.MarshalType, needsOpProc: Private.NeedsMarshaling,
vectorName: vectorName, vectorInfo: vectorInfo,
indexType: indexType, elementType: elementType,
marshalInfo: marshalInfo ];
END;
DoVectorOperation: PROCEDURE [
opProc: OperationProc,
needsOpProc: NeedsOperationProc,
vectorName: String,
vectorInfo: ST.TypeInfo,
indexType, elementType: ST.TypeHandle,
marshalInfo: MarshalInfo,
nest: Nest ] =
BEGIN
Must generate one statement.
IF needsOpProc[elementType]
THEN BEGIN
indexName: String = Private.UniqueName[
root: "element", marshalInfo: marshalInfo];
elementName: String = IO.PutFR["%g[%g]", [rope[vectorName]], [rope[indexName]]];
WFSL[Indent[nest], "FOR "--L--, indexName, ": "--L--];
Declare.WriteTypeName[indexType];
WFS1[" IN "--L--];
SELECT vectorInfo.type FROM
Array => Declare.WriteTypeName[indexType];
Descriptor, Sequence =>
BEGIN
WFS1["[FIRST["--L--]; Declare.WriteTypeName[indexType];
WFS1["]..FIRST["--L--]; Declare.WriteTypeName[indexType];
WFSL["]+LENGTH["--L--,
(IF vectorInfo.type=Sequence THEN "DESCRIPTOR["--L-- ELSE ""--L--),
vectorName,
(IF vectorInfo.type=Sequence THEN "]"--L-- ELSE ""--L--),
"])"--L--];
END;
ENDCASE => ERROR;
WFS1[" DO\n"--L--];
opProc[ nest: nest+1,
name: elementName, type: elementType,
parentInfo: [vectorName, vectorInfo],
marshalInfo: marshalInfo ];
WFL[nest+1, "ENDLOOP; -- FOR "--L--, indexName, "."--L--];
END;
END;
Marshaling utility routines.
MakeRefsNil: OperationProc =
BEGIN
Make only refs in safe storage NIL, not those in pkts.
IF marshalInfo.direction=fromPkt AND Private.ContainsRefs[type: type]
THEN BEGIN
WFL1[nest, "-- Restore garbled REFs to NIL following copy."--L--];
AssignNilToRefs[ nest: nest,
name: name, type: type,
parentInfo: parentInfo, marshalInfo: marshalInfo ];
END;
END;
AssignNilToRefs: OperationProc =
BEGIN
typeInfo: ST.TypeInfo = ST.GetTypeInfo[type: type];
SELECT marshalInfo.paramFieldInfo.passingMethod FROM
Handle => NULL;
InterMds => ERROR;
Var, Value, Result =>
WITH typeInfo: typeInfo SELECT FROM
Null, Definition, Basic,
Pointer, RelativePtr, String, StringBody, Text,
Any, Opaque, Zone, Other => NULL;
Ref, List, Rope, Atom, Transfer =>
WFLL[nest,
"LOOPHOLE["--L--, name, ", "--L--,
(IF typeInfo.type#Transfer THEN "LONG "--L-- ELSE ""--L--),
"POINTER] ← NIL;"--L-- ];
Record =>
DoRecordOperation[ nest: nest,
opProc: AssignNilToRefs, needsOpProc: Private.ContainsRefs,
recName: name,
recInfo: typeInfo,
marshalInfo: marshalInfo ];
VariantPart =>
DoVariantOperation[ nest: nest,
opProc: AssignNilToRefs, needsOpProc: Private.ContainsRefs,
varName: name,
varInfo: typeInfo,
marshalInfo: marshalInfo ];
Array =>
DoVectorOperation[ nest: nest,
opProc: AssignNilToRefs, needsOpProc: Private.ContainsRefs,
vectorName: name,
vectorInfo: typeInfo,
indexType: typeInfo.indexType, elementType: typeInfo.elementType,
marshalInfo: marshalInfo ];
Descriptor =>
DoVectorOperation[ nest: nest,
opProc: AssignNilToRefs, needsOpProc: Private.ContainsRefs,
vectorName: name,
vectorInfo: typeInfo,
indexType: typeInfo.indexType, elementType: typeInfo.elementType,
marshalInfo: marshalInfo ];
Sequence =>
DoVectorOperation[ nest: nest,
opProc: AssignNilToRefs, needsOpProc: Private.ContainsRefs,
vectorName: name,
vectorInfo: typeInfo,
indexType: typeInfo.indexType, elementType: typeInfo.elementType,
marshalInfo: marshalInfo ];
ENDCASE => ERROR;
ENDCASE => ERROR;
END;
FieldName: PROCEDURE [
recordName: String ← "record",
recordType: ST.TypeHandle,
fieldSymbol: ST.SymbolHandle,
anonOk: BOOLEANFALSE ]
RETURNS [recordDotField: String ← NIL] =
BEGIN
IF anonOk OR ~ST.IsAnonymous[symbol: fieldSymbol]
THEN recordDotField ← recordName.Cat[".", ST.SymbolName[fieldSymbol]]
ELSE BEGIN
Private.Error[code: AnonymousIdentifier, type: recordType];
recordDotField ← "record.unnamedField";
END;
END;
END. -- LupineMarshalTypeConstructorImpl.