Initial support for compound literals.

Compound literals outside of functions should work at this point.

Compound literals inside of functions are not fully implemented, so they are disabled for now. (There is some code to support them, but the code to actually initialize them at the appropriate time is not written yet.)
This commit is contained in:
Stephen Heumann 2021-09-15 22:22:16 -05:00
parent 3c3697535e
commit 7ae830ae7e
4 changed files with 117 additions and 5 deletions

View File

@ -360,10 +360,11 @@ type
isForwardDeclared: boolean; {does this var use a forward declared type?} isForwardDeclared: boolean; {does this var use a forward declared type?}
class: tokenEnum; {storage class} class: tokenEnum; {storage class}
case storage: storageType of case storage: storageType of
stackFrame: (lln: integer); {local label #} stackFrame: (lln: integer; {local label #}
parameter: (pln: integer; {paramater label #} clnext: identPtr); {next compound literal}
pdisp: integer; {disp of parameter} parameter: (pln: integer; {paramater label #}
pnext: identPtr); {next parameter} pdisp: integer; {disp of parameter}
pnext: identPtr); {next parameter}
external: (); external: ();
global,private: (); global,private: ();
none: (); none: ();

View File

@ -268,6 +268,14 @@ function MakeFuncIdentifier: identPtr; extern;
{ } { }
{ This must only be called within a function body. } { This must only be called within a function body. }
function MakeCompoundLiteral(tp: typePtr): identPtr; extern;
{ Make the identifier for a compound literal. }
{ }
{ parameters: }
{ tp - the type of the compound literal }
{-- External unsigned math routines ----------------------------} {-- External unsigned math routines ----------------------------}
function lshr (x,y: longint): longint; extern; function lshr (x,y: longint): longint; extern;
@ -2001,6 +2009,49 @@ var
end; {DoGeneric} end; {DoGeneric}
procedure DoCompoundLiteral;
{ process a compound literal expression }
label 1;
var
id: identPtr;
sp: tokenPtr;
begin {DoCompoundLiteral}
if kind in [preprocessorExpression,arrayExpression] then begin
op := opStack;
while op <> nil do begin
if op^.token.kind = sizeofsy then
goto 1;
op := op^.next;
end; {while}
Error(41);
errorFound := true;
end; {if}
1:
id := MakeCompoundLiteral(opStack^.castType);
opStack := opStack^.next;
{create an operand on the stack}
new(sp);
sp^.token.kind := ident;
sp^.token.class := identifier;
sp^.token.symbolPtr := id;
sp^.token.name := id^.name;
sp^.id := id;
sp^.next := stack;
sp^.left := nil;
sp^.middle := nil;
sp^.right := nil;
stack := sp;
ComplexTerm;
expectingTerm := false;
end; {DoCompoundLiteral}
begin {ExpressionTree} begin {ExpressionTree}
opStack := nil; opStack := nil;
stack := nil; stack := nil;
@ -2147,6 +2198,10 @@ if token.kind in startExpression then begin
parenCount := parenCount+1; parenCount := parenCount+1;
end; end;
end {else if} end {else if}
else if (token.kind = lbracech) {handle a compound literal}
and (opstack <> nil) and (opStack^.token.kind = castoper) then begin
DoCompoundLiteral
end {else if}
else if token.kind = _Genericsy then {handle _Generic} else if token.kind = _Genericsy then {handle _Generic}
DoGeneric DoGeneric
else begin {handle an operation...} else begin {handle an operation...}

View File

@ -69,6 +69,14 @@ function MakeFuncIdentifier: identPtr;
{ This must only be called within a function body. } { This must only be called within a function body. }
function MakeCompoundLiteral(tp: typePtr): identPtr;
{ Make the identifier for a compound literal. }
{ }
{ parameters: }
{ tp - the type of the compound literal }
procedure InitParser; procedure InitParser;
{ Initialize the parser } { Initialize the parser }
@ -176,6 +184,8 @@ var
statementList: statementPtr; {list of open statements} statementList: statementPtr; {list of open statements}
savedVolatile: boolean; {saved copy of volatile} savedVolatile: boolean; {saved copy of volatile}
doingForLoopClause1: boolean; {doing the first clause of a for loop?} doingForLoopClause1: boolean; {doing the first clause of a for loop?}
compoundLiteralNumber: integer; {number of compound literal}
compoundLiteralToAllocate: identPtr; {compound literal that needs space allocated}
{parameter processing variables} {parameter processing variables}
{------------------------------} {------------------------------}
@ -325,6 +335,11 @@ var
stPtr: statementPtr; {work pointer} stPtr: statementPtr; {work pointer}
begin {EndCompoundStatement} begin {EndCompoundStatement}
while compoundLiteralToAllocate <> nil do begin {allocate compound literals}
Gen2(dc_loc, compoundLiteralToAllocate^.lln,
long(compoundLiteralToAllocate^.itype^.size).lsw);
compoundLiteralToAllocate := compoundLiteralToAllocate^.clnext;
end {while};
dumpLocal := false; dumpLocal := false;
stPtr := statementList; {pop the statement record} stPtr := statementList; {pop the statement record}
statementList := stPtr^.next; statementList := stPtr^.next;
@ -4093,7 +4108,7 @@ begin {TypeName}
DeclarationSpecifiers(specifierQualifierListElement, rparench); DeclarationSpecifiers(specifierQualifierListElement, rparench);
{_Alignas is not allowed in most uses of type names. } {_Alignas is not allowed in most uses of type names. }
{It would be allowed in compound literals, if we supported them.} {TODO: _Alignas should be allowed in compound literals. }
if _Alignassy in declarationModifiers then if _Alignassy in declarationModifiers then
Error(142); Error(142);
@ -4534,6 +4549,44 @@ MakeFuncIdentifier := id;
end; {MakeFuncIdentifier} end; {MakeFuncIdentifier}
function MakeCompoundLiteral{tp: typePtr): identPtr};
{ Make the identifier for a compound literal. }
{ }
{ parameters: }
{ tp - the type of the compound literal }
type
nameString = packed array [0..24] of char;
var
id: identPtr; {the identifier for the literal}
name: ^nameString; {the name for the identifier}
class: tokenEnum; {storage class}
begin {MakeCompoundLiteral}
if functionTable <> nil then begin
Error(164);
class := autosy
end {if}
else
class := staticsy;
name := pointer(Malloc(25));
name^ := concat('~CompoundLiteral', cnvis(compoundLiteralNumber));
id := NewSymbol(name, tp, class, variableSpace, defined);
Initializer(id);
MakeCompoundLiteral := id;
compoundLiteralNumber := compoundLiteralNumber + 1;
if compoundLiteralNumber = 0 then
Error(57);
if class = autosy then begin
id^.lln := GetLocalLabel;
id^.clnext := compoundLiteralToAllocate;
compoundLiteralToAllocate := id;
end;
end; {MakeFuncIdentifier}
procedure InitParser; procedure InitParser;
{ Initialize the parser } { Initialize the parser }
@ -4554,6 +4607,8 @@ statementList := nil; {no open statements}
codegenStarted := false; {code generator is not started} codegenStarted := false; {code generator is not started}
doingForLoopClause1 := false; {not doing a for loop} doingForLoopClause1 := false; {not doing a for loop}
fIsNoreturn := false; {not doing a noreturn function} fIsNoreturn := false; {not doing a noreturn function}
compoundLiteralNumber := 1; {no compound literals yet}
compoundLiteralToAllocate := nil; {no compound literals needing space yet}
{init syntactic classes of tokens} {init syntactic classes of tokens}
{See C17 section 6.7 ff.} {See C17 section 6.7 ff.}

View File

@ -720,6 +720,7 @@ if list or (numErr <> 0) then begin
161: msg := @'illegal operator in a constant expression'; 161: msg := @'illegal operator in a constant expression';
162: msg := @'invalid escape sequence'; 162: msg := @'invalid escape sequence';
163: msg := @'pointer assignment discards qualifier(s)'; 163: msg := @'pointer assignment discards qualifier(s)';
164: msg := @'compound literals within functions are not supported by ORCA/C';
otherwise: Error(57); otherwise: Error(57);
end; {case} end; {case}
writeln(msg^); writeln(msg^);