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 ],
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;
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;