File [Ivy]<Nelson>Lupine>LupineMarshalTypeManagerImpl.mesa.
Last edited by BZM on 11-May-82 16:20:51.
This module cooperates with LupineMarshal*Impl to export LupineMarshal.
Last Edited by: Birrell, September 12, 1983 3:41 pm
DIRECTORY
IO USING [PutFR],
LupineDeclare USING [
ParameterName, WriteParameterName, WriteTypeName ],
LupineManagerPrivate USING [
Indent, Nest, ParamPassingMethod, String, StringNIL,
WF1, WFS, WFS1, WFSL, WFL, WFL1, WFLL ],
LupineMarshal USING [
FieldInfo, ParamIndex, ParamInfo,
ParamProcedure, ParamRecordKind, OverlayHandling,
OverlayParamType, VariableNames, Version ],
LupineMarshalPrivate USING [
ContainsEmbeddedPtrs,
CopyCharacters, CopyOne, CopyTwo, CopyType, CopyUninterpreted,
Direction, EnumerateFrameParams, EnumerateOverlayParams, Error,
IsExplicitHandle, IsShortString,
MarshalInfo, MarshalInfoObject,
MarshalArray, MarshalDescriptor, MarshalList,
MarshalPointer, MarshalRecord, MarshalRef,
MarshalSequence, MarshalTransfer,MarshalVariantPart,
OperationProc,
ParentInfo, ParentInfoNull, Passing,
SubStrings, WriteNEW ],
LupineSymbolTable USING [GetTypeInfo, TypeHandle, TypeInfo, Types];
LupineMarshalTypeManagerImpl: PROGRAM
IMPORTS
IO, Declare: LupineDeclare, LupineManagerPrivate,
Private: LupineMarshalPrivate, ST: LupineSymbolTable
EXPORTS LupineMarshal, LupineMarshalPrivate
= BEGIN OPEN LupineManagerPrivate, LupineMarshal;
Types from the internal LupineManagerPrivate interface.
ParentInfo: TYPE = Private.ParentInfo;
MarshalInfo: TYPE = Private.MarshalInfo;
Parameter protocol versions:
ParameterProtocolVersions: PUBLIC PROCEDURE
RETURNS [oldestSupported, newestSupported: Version] =
{RETURN [
oldestSupported: 1,
newestSupported: 1 ]};
These routines generate marshaling code for top-level parameters.
ToPacket: PUBLIC PROCEDURE [
paramInfo: ParamInfo,
overlayHandling: OverlayHandling,
varNames: VariableNames,
nest: Nest ] =
BEGIN
overlayNeedsMoving: BOOLEANFALSE;
construct: BOOLEANTRUE; -- Assign, not construct, when FALSE.
FOR overlayType: OverlayParamType
IN [FIRST[OverlayParamType]..PRED[LAST[OverlayParamType]]] DO
IF paramInfo.hasOverlayParamType[overlayType]
THEN SELECT overlayHandling[overlayType] FROM
copyToPkt => overlayNeedsMoving ← TRUE;
ENDCASE => construct ← FALSE;
Must use assignment when whole record can't be constructed.
ENDLOOP;
IF overlayNeedsMoving
THEN BEGIN -- Move some overlay params from local frame to pkt.
printedOne: BOOLEANFALSE;
MoveOverlayParam: ParamProcedure =
BEGIN
SELECT overlayHandling[paramFieldInfo.overlayParamType] FROM
alreadyInPkt => NULL;
copyToPkt =>
BEGIN
IF construct
THEN {IF printedOne THEN WFS1[", "--L--] ELSE printedOne ← TRUE}
ELSE WFS[Indent[nest], varNames.overlayPtr, "."--L--];
Declare.WriteParameterName[paramName, paramIndex];
WFS1[IF construct THEN ": "--L-- ELSE " ← "--L--];
Declare.WriteParameterName[paramName, paramIndex];
IF ~construct THEN WFS1[";\n"--L--];
END;
ENDCASE => ERROR;
END; -- MoveOverlayParam.
IF construct THEN WFS[Indent[nest], varNames.overlayPtr, "^ ← ["--L--];
Private.EnumerateOverlayParams[paramInfo, MoveOverlayParam];
IF construct THEN WFS1["];\n"--L--];
END; -- Move the overlay params.
BEGIN -- Move remaining nonoverlay params from local frame to pkt.
marshalInfoObject: Private.MarshalInfoObject ← [
paramInfo: paramInfo,
paramFieldInfo: NULL,
varNames: varNames,
direction: toPkt ];
marshalInfo: MarshalInfo = @marshalInfoObject;
MarshalFrameParam: ParamProcedure =
BEGIN
marshalInfo.paramFieldInfo ← paramFieldInfo;
MarshalType[ nest: nest,
name: Declare.ParameterName[paramName, paramIndex],
type: paramType,
parentInfo: Private.ParentInfoNull,
marshalInfo: marshalInfo ];
END; -- MarshalFrameParam.
Private.EnumerateFrameParams[paramInfo, MarshalFrameParam];
END; -- Move the remaining nonoverlay params.
END;
FromPacket: PUBLIC PROCEDURE [
paramInfo: ParamInfo,
overlayHandling: OverlayHandling,
varNames: VariableNames,
nest: Nest ] =
BEGIN
overlayNeedsMoving: BOOLEANFALSE;
FOR overlayType: OverlayParamType IN OverlayParamType DO
IF paramInfo.hasOverlayParamType[overlayType] AND
overlayHandling[overlayType] IN [copyToFrame..justCopyToFrame]
THEN {overlayNeedsMoving ← TRUE; EXIT};
ENDLOOP;
IF overlayNeedsMoving
THEN BEGIN -- Move some overlay params from pkt to local frame.
printedOne: BOOLEANFALSE;
ExtractOverlayParam: ParamProcedure =
BEGIN
SELECT overlayHandling[paramFieldInfo.overlayParamType] FROM
leaveInPkt => NULL;
copyToFrame, justCopyToFrame =>
BEGIN
IF printedOne THEN WFS1[", "--L--] ELSE printedOne ← TRUE;
Declare.WriteParameterName[paramName, paramIndex];
WFS1[": "--L--];
Declare.WriteParameterName[paramName, paramIndex];
END;
ENDCASE => ERROR;
END; -- ExtractOverlayParam.
WFS[Indent[nest], "["--L--];
Private.EnumerateOverlayParams[paramInfo, ExtractOverlayParam];
WFS["] ← "--L--, varNames.overlayPtr, "^;\n"--L--];
END; -- Move the overlay params.
FOR overlayType: OverlayParamType IN OverlayParamType DO
IF overlayHandling[overlayType] = justCopyToFrame THEN RETURN;
ENDLOOP;
BEGIN -- Move remaining nonoverlay params from local frame to pkt.
marshalInfoObject: Private.MarshalInfoObject ← [
paramInfo: paramInfo,
paramFieldInfo: NULL,
varNames: varNames,
direction: fromPkt ];
marshalInfo: MarshalInfo = @marshalInfoObject;
MarshalFrameParam: ParamProcedure =
BEGIN
marshalInfo.paramFieldInfo ← paramFieldInfo;
MarshalType[ nest: nest,
name: Declare.ParameterName[paramName, paramIndex],
type: paramType,
parentInfo: Private.ParentInfoNull,
marshalInfo: marshalInfo ];
END; -- MarshalFrameParam.
Private.EnumerateFrameParams[paramInfo, MarshalFrameParam];
END; -- Move the remaining nonoverlay params.
BEGIN -- Check that the correct amount of pkt.data was unmarshaled.
HasInFrameParams: PROC [paramInfo: ParamInfo] RETURNS [BOOLEAN] =
This routine is used to perform constant folding on "pktLength".
See LupineDeclareStubsImpl.PacketLength.
INLINE {RETURN[
paramInfo.adrInfo.hasAddresses OR
paramInfo.adrInfo.hasDynamics OR
~paramInfo.alwaysOnePkt ]};
WFSL[Indent[nest], "Lupine.CheckPktLength[pkt: ", varNames.pkt,
", pktLength: "];
IF HasInFrameParams[paramInfo]
THEN WFS1[varNames.pktLength]
ELSE WF1["%g", [integer[paramInfo.sizeOf.overlayParamRecord]]];
WFS1["];\n"];
END;
END;
General type marshaling routine.
OperationInfo: TYPE = RECORD [
canMarshal: BOOLEANTRUE,
newBlock: BOOLEANTRUE] ← [];
MarshalOpInfo: PACKED ARRAY ST.Types OF OperationInfo = [
These four must have a block because of Start/StopReadonly.
Pointer: [newBlock: TRUE],
Ref: [newBlock: TRUE],
List: [newBlock: TRUE],
Descriptor: [newBlock: TRUE],
These are simple and don't need a block.
Null: [newBlock: FALSE],
Basic: [newBlock: FALSE],
Transfer: [newBlock: FALSE],
VariantPart: [newBlock: FALSE],
RelativePtr: [newBlock: FALSE],
Zone: [newBlock: FALSE],
Opaque: [newBlock: FALSE],
These guys cannot be marshaled.
Definition: [canMarshal: FALSE, newBlock: FALSE],
Any: [canMarshal: FALSE, newBlock: FALSE],
Other: [canMarshal: FALSE, newBlock: FALSE] ];
MarshalType: PUBLIC Private.OperationProc =
BEGIN
Each marshaling routine for which MarshalOpInfo.newBlock is TRUE can
generate multiple statements because BEGIN-END is written here.
Otherwise the routine must generate exactly one statement.
Explain: ARRAY {verb, adverb} OF ARRAY Private.Direction OF String = [
verb: [toPkt: "Marshal"--L--, fromPkt: "Unmarshal"--L--],
adverb: [toPkt: "to"--L--, fromPkt: "from"--L--] ];
typeInfo: ST.TypeInfo = ST.GetTypeInfo[type: type];
passingMethod: ParamPassingMethod = marshalInfo.paramFieldInfo.passingMethod;
marshalInfo.depth ← marshalInfo.depth + 1;
IF MarshalOpInfo[typeInfo.type].newBlock
THEN BEGIN
WFSL[ Indent[nest], "BEGIN -- "--L--,
Explain[verb][marshalInfo.direction], " "--L--, name, ": "--L-- ];
Declare.WriteTypeName[type];
WFSL[ " "--L--, Explain[adverb][marshalInfo.direction], " "--L--,
marshalInfo.varNames.pkt, ".data["--L--, marshalInfo.varNames.pktLength,
"].\n"--L-- ];
nest ← nest + 1;
END;
IF MarshalOpInfo[typeInfo.type].canMarshal
THEN SELECT passingMethod FROM
Handle, InterMds =>
BEGIN
Handle and InterMds should only happen at the top (param) level.
IF marshalInfo.depth # 1 THEN ERROR;
Private.CopyUninterpreted[ nest: nest,
variableName: name, variableInfo: typeInfo,
parentInfo: parentInfo, marshalInfo: marshalInfo ];
END;
Var, Value, Result =>
SELECT TRUE FROM
(passingMethod = Result OR passingMethod = Var) AND
Private.ContainsEmbeddedPtrs[type] =>
Exactly one pointer depth is permitted in VAR and RESULT.
Private.Error[code: EmbeddedRESULT, type: type];
Private.IsExplicitHandle[typeInfo] =>
A handle embedded in something else still a handle.
Private.CopyUninterpreted[ nest: nest,
variableName: name, variableInfo: typeInfo,
parentInfo: parentInfo, marshalInfo: marshalInfo ];
ENDCASE =>
BEGIN
marshalName: String = StartReadonly[ nest: nest,
name: name, typeInfo: typeInfo,
marshalInfo: marshalInfo ];
WITH typeInfo: typeInfo SELECT FROM
Null, Basic, RelativePtr, Opaque =>
These basic types just need copying.
Private.CopyType[ nest: nest,
variableName: marshalName, variableInfo: typeInfo,
parentInfo: parentInfo, marshalInfo: marshalInfo ];
Transfer => Private.MarshalTransfer[
marshalName, typeInfo, parentInfo, marshalInfo, nest];
Record => Private.MarshalRecord[
marshalName, typeInfo, parentInfo, marshalInfo, nest];
VariantPart => Private.MarshalVariantPart[
marshalName, typeInfo, parentInfo, marshalInfo, nest];
Pointer => Private.MarshalPointer[
marshalName, typeInfo, parentInfo, marshalInfo, nest];
Ref => Private.MarshalRef[
marshalName, typeInfo, parentInfo, marshalInfo, nest];
List => Private.MarshalList[
marshalName, typeInfo, parentInfo, marshalInfo, nest];
String => MarshalString[
marshalName, typeInfo, parentInfo, marshalInfo, nest];
Rope => MarshalRope[
marshalName, typeInfo, parentInfo, marshalInfo, nest];
Atom => MarshalAtom[
marshalName, typeInfo, parentInfo, marshalInfo, nest];
StringBody => MarshalStringBody[
marshalName, typeInfo, parentInfo, marshalInfo, nest];
Text => MarshalText[
marshalName, typeInfo, parentInfo, marshalInfo, nest];
Array => Private.MarshalArray[
marshalName, typeInfo, parentInfo, marshalInfo, nest];
Descriptor => Private.MarshalDescriptor[
marshalName, typeInfo, parentInfo, marshalInfo, nest];
Sequence => Private.MarshalSequence[
marshalName, typeInfo, parentInfo, marshalInfo, nest];
Zone => -- Zones must be handles.
Private.Error[code: ImproperPassingMethod, type: type];
Definition, Any, Other =>
ERROR; -- Unimplemented marshalings should be caught above.
ENDCASE => ERROR;
StopReadonly[ nest: nest,
name: name, typeInfo: typeInfo,
marshalName: marshalName, marshalInfo: marshalInfo ];
END;
ENDCASE => ERROR
ELSE Private.Error[code: UnimplementedMarshaling, type: type];
IF MarshalOpInfo[typeInfo.type].newBlock
THEN WFLL[nest, "END; -- "--L--, Explain[verb][marshalInfo.direction],
" "--L--, name, "."--L-- ];
marshalInfo.depth ← marshalInfo.depth - 1;
END;
Marshaling routines for nontrivial builtin types (e.g., strings).
MarshalString: PROCEDURE [
name: String,
stringInfo: String ST.TypeInfo,
parentInfo: ParentInfo,
marshalInfo: MarshalInfo,
nest: Nest ] =
INLINE BEGIN
MarshalStringTypes[ nest: nest,
stringInfo: stringInfo,
parentInfo: [name, stringInfo],
marshalInfo: marshalInfo ];
END;
MarshalStringBody: PROCEDURE [
name: String,
stringBodyInfo: StringBody ST.TypeInfo,
parentInfo: ParentInfo,
marshalInfo: MarshalInfo,
nest: Nest ] =
INLINE BEGIN
MarshalStringTypes[ nest: nest,
stringInfo: stringBodyInfo,
parentInfo: parentInfo,
marshalInfo: marshalInfo ];
END;
MarshalText: PROCEDURE [
name: String,
textInfo: Text ST.TypeInfo,
parentInfo: ParentInfo,
marshalInfo: MarshalInfo,
nest: Nest ] =
INLINE BEGIN
MarshalStringTypes[ nest: nest,
stringInfo: textInfo,
parentInfo: parentInfo,
marshalInfo: marshalInfo ];
END;
MarshalStringTypes: PROCEDURE [
stringInfo: ST.TypeInfo,
parentInfo: ParentInfo,
marshalInfo: MarshalInfo,
nest: Nest ] =
BEGIN
DotMaxLength: String = SELECT stringInfo.type FROM
String, StringBody => ".maxlength",
Text => ".maxLength",
ENDCASE => ERROR;
TextBase: Private.SubStrings = SELECT stringInfo.type FROM
String, StringBody => ["BASE[", parentInfo.name, ".text]"],
Text => ["BASE[DESCRIPTOR[", parentInfo.name, ".text]]"],
ENDCASE => ERROR;
VerifyPassingMethods[all: TRUE, marshalInfo: marshalInfo];
SELECT parentInfo.typeInfo.type FROM
String, Pointer, Ref => NULL; ENDCASE => ERROR;
SELECT marshalInfo.direction FROM
toPkt =>
BEGIN
Private.CopyOne[ nest: nest,
wordsNeeded: 3,
value: [parentInfo.name, "=NIL"],
marshalInfo: marshalInfo ];
WFL[nest, "IF ", parentInfo.name, " # NIL"];
WFL1[nest+1, "THEN BEGIN"];
WFL1[nest+2, "stringHeader: Lupine.StringHeader = ["];
WFLL[nest+3,
"Lengths[length: ", parentInfo.name, ".length, maxLength: ",
parentInfo.name, DotMaxLength, "]];" ];
IF Private.IsShortString[stringInfo.self]
THEN BEGIN
WFL[nest+2,
"IF stringHeader.length > RpcPrivate.maxShortStringLength"];
WFL1[nest+3, "THEN Lupine.MarshalingError;"];
END;
Private.CopyTwo[ nest: nest+2,
wordsNeeded: 0,
value: ["stringHeader.all"],
marshalInfo: marshalInfo ];
IF Private.Passing[Result, argument, marshalInfo]
THEN WFL1[nest+2, "NULL; -- Call by result, send header only."]
ELSE Private.CopyCharacters[ nest: nest+2,
textName: TextBase,
numCharsName: "stringHeader.length",
marshalInfo: marshalInfo ];
WFL[nest+2, "END; -- IF ", parentInfo.name, " # NIL."];
END;
fromPkt =>
BEGIN
WFL1[nest, "stringIsNIL: Lupine.NilHeader;"];
Private.CopyOne[ nest: nest,
wordsNeeded: 3,
value: ["stringIsNIL"],
marshalInfo: marshalInfo ];
IF Private.Passing[Result, result, marshalInfo] OR
Private.Passing[Var,result,marshalInfo]
THEN WFL[nest,
"IF stringIsNIL # (", parentInfo.name,
"=NIL) THEN Lupine.UnmarshalingError;"];
WFL1[nest, "IF stringIsNIL"];
WFL[nest+1, "THEN ", parentInfo.name, " ← NIL"];
WFL1[nest+1, "ELSE BEGIN"];
WFL1[nest+2, "stringHeader: Lupine.StringHeader;"];
Private.CopyTwo[ nest: nest+2,
wordsNeeded: 0,
value: ["stringHeader.all"],
marshalInfo: marshalInfo ];
IF Private.IsShortString[stringInfo.self]
THEN BEGIN
WFL[nest+2,
"IF stringHeader.length > RpcPrivate.maxShortStringLength"];
WFL1[nest+3, "THEN Lupine.UnmarshalingError;"];
END;
IF Private.Passing[Result, result, marshalInfo] OR
Private.Passing[Var,result,marshalInfo]
THEN BEGIN
WFLL[nest+2,
"IF stringHeader.maxLength # ", parentInfo.name, DotMaxLength,
" THEN Lupine.UnmarshalingError;" ];
WFL1[nest+2,
"NULL; -- Call by var or result, use existing string."];
END
ELSE BEGIN
WFS[Indent[nest+2], parentInfo.name, " ← ("];
Private.WriteNEW[ptrInfo: parentInfo.typeInfo, marshalInfo: marshalInfo];
WFS1["["];
SELECT stringInfo.type FROM
String => WFS1["StringBody"];
ENDCASE => Declare.WriteTypeName[stringInfo.self];
WFS1["[stringHeader.maxLength]]);\n"];
END;
IF Private.Passing[Result, argument, marshalInfo]
THEN WFL1[nest+2, "NULL; -- Call by result, use uninitialized body."]
ELSE BEGIN
WFL[nest+2, parentInfo.name, ".length ← stringHeader.length;"];
Private.CopyCharacters[ nest: nest+2,
textName: TextBase,
numCharsName: "stringHeader.length",
marshalInfo: marshalInfo ];
END;
WFL[nest+2, "END; -- IF stringIsNIL."];
END;
ENDCASE => ERROR;
END;
MarshalRope: PROCEDURE [
name: String,
ropeInfo: Rope ST.TypeInfo,
parentInfo: ParentInfo,
marshalInfo: MarshalInfo,
nest: Nest ] =
BEGIN
VerifyPassingMethods[value: TRUE, handle: TRUE, marshalInfo: marshalInfo];
SELECT marshalInfo.direction FROM
toPkt =>
BEGIN
Private.CopyOne[ nest: nest,
wordsNeeded: 2,
value: [name, "=NIL"],
marshalInfo: marshalInfo ];
WFL[nest, "IF ", name, " # NIL"];
WFL1[nest+1, "THEN BEGIN"];
WFL[nest+2,
"textRope: Rope.Text = Rope.InlineFlatten[r: ", name, "];"];
IF Private.IsShortString[ropeInfo.self] THEN BEGIN
WFL1[nest+2, "IF textRope.length > RpcPrivate.maxShortStringLength"];
WFL1[nest+3, "THEN Lupine.MarshalingError;"];
END;
Private.CopyOne[ nest: nest+2,
wordsNeeded: 0,
value: ["textRope.length"],
marshalInfo: marshalInfo ];
Private.CopyCharacters[ nest: nest+2,
textName: ["BASE[DESCRIPTOR[textRope.text]]"],
numCharsName: "textRope.length",
marshalInfo: marshalInfo ];
WFL[nest+2, "END; -- IF ", name, " # NIL."];
END;
fromPkt =>
BEGIN
WFL1[nest, "ropeIsNIL: Lupine.NilHeader;"];
Private.CopyOne[ nest: nest,
wordsNeeded: 2,
value: ["ropeIsNIL"],
marshalInfo: marshalInfo ];
WFL1[nest, "IF ropeIsNIL"];
WFL[nest+1, "THEN ", name, " ← NIL"];
WFL1[nest+1, "ELSE BEGIN"];
WFL1[nest+2, "ropeLength: Lupine.RopeHeader;"];
WFL1[nest+2, "textRope: Rope.Text;"];
Private.CopyOne[ nest: nest+2,
wordsNeeded: 0,
value: ["ropeLength"],
marshalInfo: marshalInfo ];
WFL[nest+2,
"IF ropeLength > ",
(IF Private.IsShortString[ropeInfo.self]
THEN "RpcPrivate.maxShortStringLength" ELSE "LAST[NAT]") ];
WFL1[nest+3, "THEN Lupine.UnmarshalingError;"];
WFL[nest+2, name, " ← textRope ← Rope.NewText[size: ropeLength];"];
Private.CopyCharacters[ nest: nest+2,
textName: ["BASE[DESCRIPTOR[textRope.text]]"],
numCharsName: "ropeLength",
marshalInfo: marshalInfo ];
WFL[nest+2, "END; -- IF ropeIsNIL."];
END;
ENDCASE => ERROR;
END;
MarshalAtom: PROCEDURE [
name: String,
atomInfo: Atom ST.TypeInfo,
parentInfo: ParentInfo,
marshalInfo: MarshalInfo,
nest: Nest ] =
BEGIN
VerifyPassingMethods[value: TRUE, handle: TRUE, marshalInfo: marshalInfo];
SELECT marshalInfo.direction FROM
toPkt =>
BEGIN
WFL[nest, "pNameOfAtom: Rope.Text = Atom.GetPName[atom: ", name, "];"];
MarshalRope[ nest: nest,
name: "pNameOfAtom",
ropeInfo: ST.TypeInfo[self: atomInfo.self, info: Rope[]],
parentInfo: parentInfo, marshalInfo: marshalInfo ];
END;
fromPkt =>
BEGIN
WFL1[nest, "pNameOfAtom: Rope.ROPE;"];
MarshalRope[ nest: nest,
name: "pNameOfAtom",
ropeInfo: ST.TypeInfo[self: atomInfo.self, info: Rope[]],
parentInfo: parentInfo, marshalInfo: marshalInfo ];
WFL[nest, name, " ← Atom.MakeAtom[--pName:-- pNameOfAtom];"];
END;
ENDCASE => ERROR;
END;
Marshaling utility routines.
VerifyPassingMethods: PUBLIC PROCEDURE [
var, value, result, handle, all: BOOLEANFALSE,
marshalInfo: MarshalInfo ] =
BEGIN
VerifyPassingMethods double checks that Lupine's
type checker (LupineMarshalInfoImpl.DeterminePassingMethod)
and code generators (the Marshal<type> routines) are in agreement.
IF marshalInfo.depth = 1 AND
NOT (all OR (SELECT marshalInfo.paramFieldInfo.passingMethod FROM
Var => var, Value => value, Result => result, Handle => handle,
InterMds => TRUE, ENDCASE => ERROR) )
THEN ERROR;
END;
UniqueName: PUBLIC PROCEDURE [
root: String,
suffix: String ← StringNIL,
marshalInfo: MarshalInfo ]
RETURNS [nameString: String] =
BEGIN
nameString ← IO.PutFR["%g%g%g", [rope[root]], [integer[marshalInfo.depth]], [rope[suffix]]];
END;
StartReadonly: PROCEDURE [
name: String,
typeInfo: ST.TypeInfo,
marshalInfo: MarshalInfo,
nest: Nest ]
RETURNS [marshalName: String] =
BEGIN
marshalName ← name; -- Usually no new name is needed.
SELECT typeInfo.type FROM
Pointer, Ref, List, Descriptor =>
IF typeInfo.readonly THEN BEGIN
marshalName ← UniqueName[
root: "writeOk",
marshalInfo: marshalInfo ];
WFL1[nest,
"-- Declare readwrite pointer for marshaling readonly pointer."];
SELECT marshalInfo.direction FROM
toPkt =>
BEGIN
WFS[Indent[nest], marshalName, ": "];
Declare.WriteTypeName[type: typeInfo.self, includeReadonly: FALSE];
WFS[" = LOOPHOLE[", name, "];\n"];
END;
fromPkt =>
BEGIN
WFS[Indent[nest], marshalName, ": "];
Declare.WriteTypeName[type: typeInfo.self, includeReadonly: FALSE];
WFS1[";\n"];
END;
ENDCASE => ERROR;
END;
ENDCASE => IF typeInfo.readonly THEN ERROR;
END;
StopReadonly: PROCEDURE [
name: String,
typeInfo: ST.TypeInfo,
marshalName: String,
marshalInfo: MarshalInfo,
nest: Nest ] =
BEGIN
SELECT typeInfo.type FROM
Pointer, Ref, List, Descriptor =>
IF typeInfo.readonly THEN
SELECT marshalInfo.direction FROM
toPkt => NULL;
fromPkt => WFLL[nest, name, " ← ", marshalName, ";"];
ENDCASE => ERROR;
ENDCASE => IF typeInfo.readonly THEN ERROR;
END;
END. -- LupineMarshalTypeManagerImpl.