Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
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>");

Copilot AI Aug 11, 2025

Copy link

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
Copy Markdown
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
Copy Markdown
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

Copilot AI Aug 11, 2025

Copy link

Choose a reason for hiding this comment

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

The grammar rule only allows 'primitive' expressions in sequence literals, but the test file and implementation suggest it should support any expression (like variables). This should be 'expr' instead of 'primitive' to match the test usage of variable 'a'.

Copilot uses AI. Check for mistakes.

@anmolsahoo25 anmolsahoo25 Aug 11, 2025

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

current code supports primitives and idents. Do we want to support the full range of expressions in the literals?

| elems+=primitive (COMMA elems+=primitive)*

Copy link
Copy Markdown
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,23 @@
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;
Type = new SequenceType(sequenceElements[0].Type);

Copilot AI Aug 11, 2025

Copy link

Choose a reason for hiding this comment

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

This code will throw an IndexOutOfRangeException if sequenceElements is empty. The grammar allows empty sequences, but this constructor assumes at least one element exists.

Suggested change
Type = new SequenceType(sequenceElements[0].Type);
if (sequenceElements.Count > 0)
{
Type = new SequenceType(sequenceElements[0].Type);
}
else
{
// Assign a default type for empty sequences. Adjust as needed for your type system.
Type = new SequenceType(PrimitiveType.Any);
}

Copilot uses AI. Check for mistakes.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Good catch. Addressed as shown.

}

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
5 changes: 5 additions & 0 deletions Src/PCompiler/CompilerCore/TypeChecker/ExprVisitor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,11 @@ 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();
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,26 @@
machine Main {
var s1: seq[int];
var s2: seq[any];
var a: int;

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

Copy link
Copy Markdown
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);
}
}
}
Loading