Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions Src/PCompiler/CompilerCore/Backend/CSharp/CSharpCodeGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1486,6 +1486,19 @@ private void WriteExpr(CompilationContext context, StringWriter output, IPExpr p
context.Write(output, ")");
break;

case SequenceLiteralExpr sequenceLiteralExpr:
context.Write(output, $"new {GetCSharpType(sequenceLiteralExpr.Type)}(new List<IPValue>");
Copy link
Preview

Copilot AI Aug 11, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The generated C# code creates a List but should use the specific element type. For a seq[int], this should generate List or the appropriate typed collection, not List.

Copilot uses AI. Check for mistakes.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure if this needs to be addressed. The generated code needs to a pass a List to the constructor for PSeq.

context.Write(output, "{");
var sep2 = "";
foreach (var elem in sequenceLiteralExpr.SequenceElements)
{
context.Write(output, sep2);
WriteExpr(context, output, elem);
sep2 = ", ";
}
context.Write(output, "})");
break;

case ValuesExpr valuesExpr:
context.Write(output, "(");
WriteExpr(context, output, valuesExpr.Expr);
Expand Down
4 changes: 4 additions & 0 deletions Src/PCompiler/CompilerCore/Backend/Debugging/IrToPseudoP.cs
Original file line number Diff line number Diff line change
Expand Up @@ -543,6 +543,10 @@ protected override void WriteExpr(IPExpr expr)
WriteParts("null");
break;

case SequenceLiteralExpr sequenceLiteralExpr:
WriteParts("{|", sequenceLiteralExpr.SequenceElements, "|}");
break;

case SeqAccessExpr seqAccessExpr:
WriteParts("(", seqAccessExpr.SeqExpr, ")[", seqAccessExpr.IndexExpr, "]");
break;
Expand Down
7 changes: 7 additions & 0 deletions Src/PCompiler/CompilerCore/Backend/IRTransformer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,13 @@ public static void SimplifyMethod(Function function)
deps.Add(ndStore);
return (ndTemp, deps);

case SequenceLiteralExpr sequenceLiteralExpr:
(var sequenceElements, var sequenceElementDeps) = SimplifyArgPack(sequenceLiteralExpr.SequenceElements);
deps.AddRange(sequenceElementDeps);
(var seqElementsVal, var seqElementsStore) = SaveInTemporary(new SequenceLiteralExpr(location, sequenceElements));
deps.Add(seqElementsStore);
return (seqElementsVal, deps);

case SeqAccessExpr seqAccessExpr:
(var seqExpr, var seqDeps) = SimplifyExpression(seqAccessExpr.SeqExpr);
(var seqIdx, var seqIdxDeps) = SimplifyExpression(seqAccessExpr.IndexExpr);
Expand Down
2 changes: 2 additions & 0 deletions Src/PCompiler/CompilerCore/Parser/PLexer.g4
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,8 @@ LBRACK : '[' ;
RBRACK : ']' ;
LPAREN : '(' ;
RPAREN : ')' ;
LSEQ : '{|';
RSEQ : '|}';
SEMI : ';' ;
COMMA : ',' ;
DOT : '.' ;
Expand Down
5 changes: 5 additions & 0 deletions Src/PCompiler/CompilerCore/Parser/PParser.g4
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,7 @@ noParamAnonEventHandler : functionBody;
expr : primitive # PrimitiveExpr
| LPAREN unnamedTupleBody RPAREN # UnnamedTupleExpr
| LPAREN namedTupleBody RPAREN # NamedTupleExpr
| LSEQ seqElems RSEQ # SequenceLiteralExpr
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This syntax conflicts with the other definition of sequence literals in the P3.0 branch (from the parameterized test work: https://github.com/p-org/P/blame/2febcebeb4bf16f333362280f2db01dd621a333f/Src/PCompiler/CompilerCore/Parser/PParser.g4#L281

We should either come up with a common representation and handling of sequences in code and parameterized tests.

| LPAREN expr RPAREN # ParenExpr
| expr DOT field=iden # NamedTupleAccessExpr
| expr DOT field=int # TupleAccessExpr
Expand Down Expand Up @@ -212,6 +213,10 @@ floatLiteral : pre=IntLiteral? DOT post=IntLiteral # DecimalFloat
| FLOAT LPAREN base=IntLiteral COMMA exp=IntLiteral RPAREN # ExpFloat
;

seqElems :
| elems+=primitive (COMMA elems+=primitive)*
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A trickiness with this use of primitive is that it doesn't handle negative numbers: negative numbers are not primitives but are unary operator expressions.

;

unnamedTupleBody : fields+=rvalue COMMA
| fields+=rvalue (COMMA fields+=rvalue)+
;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
using System.Collections.Generic;
using System.Linq;
using Antlr4.Runtime;
using Plang.Compiler.TypeChecker.Types;

namespace Plang.Compiler.TypeChecker.AST.Expressions
{
public class SequenceLiteralExpr: IPExpr
{
public SequenceLiteralExpr(ParserRuleContext sourceLocation, IReadOnlyList<IPExpr> sequenceElements)
{
SourceLocation = sourceLocation;
SequenceElements = sequenceElements;

if (sequenceElements.Count > 0) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we determine a more general type (like seq or seq) if the sequence elements are heterogeneous?

Type = new SequenceType(sequenceElements[0].Type);
}
else {
Type = new SequenceType(PrimitiveType.Any);
}
}

public IReadOnlyList<IPExpr> SequenceElements { get; }

public ParserRuleContext SourceLocation { get; }

public PLanguageType Type { get; }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,11 @@ public override object VisitKeywordExpr(PParser.KeywordExprContext context)
return null;
}

public override object VisitSequenceLiteralExpr(PParser.SequenceLiteralExprContext context)
{
return null;
}

public override object VisitSeqAccessExpr(PParser.SeqAccessExprContext context)
{
return null;
Expand Down
17 changes: 17 additions & 0 deletions Src/PCompiler/CompilerCore/TypeChecker/ExprVisitor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,23 @@ public override IPExpr VisitTupleAccessExpr(PParser.TupleAccessExprContext conte
return new TupleAccessExpr(context, subExpr, fieldNo, tuple.Types[fieldNo]);
}

public override IPExpr VisitSequenceLiteralExpr(PParser.SequenceLiteralExprContext context) {
var elems = context.seqElems()._elems.Select(Visit).ToArray();

// check whether all elements have the same type
if (elems.Count() > 0) {
var firstElementType = elems[0].Type;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we handle a more general type (like seq or seq) if the sequence elements are heterogeneous?

for (int i = 1; i < elems.Count(); i++) {
var currElementType = elems[i].Type;
if (!currElementType.Equals(firstElementType)) {
throw handler.TypeMismatch(context.seqElems()._elems[i], currElementType, firstElementType);
}
}
}

return new SequenceLiteralExpr(context, elems);
}

public override IPExpr VisitSeqAccessExpr(PParser.SeqAccessExprContext context)
{
var seqOrMap = Visit(context.seq);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
machine Main {
var s1: seq[int];
var s2: seq[any];
var s3: seq[bool];
var a: int;

start state S
{
entry
{
s1 = {| 1 , 2 , 3 |};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add a test for a negative int; I suspect it will fail.

assert (s1[0] == 1);
assert (s1[1] == 2);
assert (s1[2] == 3);

s2 = {| true, false, true |};
assert (s2[0] as bool);
assert (!(s2[1] as bool));
assert (s2[2] as bool);

s1 = {| a, a, a |};
assert (s1[0] == 0);
assert (s1[1] == 0);
assert (s1[2] == 0);

s3 = {||} as seq[bool];
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
machine Main {
var s1 : seq[bool];

start state S
{
entry
{
s1 = {| true, 1, 2 |}; //error: "got type int, expected bool"
raise halt;
}
}
}