Skip to content

Commit 76a7158

Browse files
committed
feat: PHP 8.5 language level, Pipe operator implementation
1 parent c78b93f commit 76a7158

File tree

7 files changed

+61
-15
lines changed

7 files changed

+61
-15
lines changed

Directory.Build.props

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@
4242

4343
<PeachpieLibraryRegularExpressionsVersion>1.7.0</PeachpieLibraryRegularExpressionsVersion>
4444
<MySqlConnectorVersion>2.0.0</MySqlConnectorVersion>
45-
<ParserVersion>8.4.17524</ParserVersion>
45+
<ParserVersion>8.5.17973</ParserVersion>
4646
<PeachpieMicrosoftCodeAnalysisVersion>3.7.4</PeachpieMicrosoftCodeAnalysisVersion>
4747

4848
</PropertyGroup>

src/Peachpie.CodeAnalysis/CodeGen/Graph/BoundExpression.cs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,10 @@ internal override TypeSymbol Emit(CodeGenerator cg)
187187
returned_type = EmitSpaceship(cg);
188188
break;
189189

190+
case Operations.Pipe:
191+
returned_type = EmitPipeCall(cg);
192+
break;
193+
190194
default:
191195
throw cg.NotImplementedException(message: $"BinaryEx {this.Operation} is not implemented.", op: this);
192196
}
@@ -2085,6 +2089,17 @@ internal static TypeSymbol EmitPow(CodeGenerator cg, TypeSymbol xtype, FlowAnaly
20852089

20862090
}
20872091
}
2092+
2093+
private TypeSymbol EmitPipeCall(CodeGenerator cg)
2094+
{
2095+
// Template: ((IPhpCallable)RValue).invoke( ctx, LValue )
2096+
2097+
cg.EmitConvert(this.Right, cg.CoreTypes.IPhpCallable); // Left is already a BoundConvertToCallable
2098+
cg.EmitLoadContext();
2099+
cg.EmitConvertToPhpValue(cg.Emit(this.Left), this.Right.TypeRefMask);
2100+
2101+
return cg.EmitCall(ILOpCode.Callvirt, cg.CoreMethods.IPhpCallable.Invoke_Context_PhpValue);
2102+
}
20882103
}
20892104

20902105
partial class BoundUnaryEx

src/Peachpie.CodeAnalysis/FlowAnalysis/ExpressionAnalysis.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1286,6 +1286,9 @@ TypeRefMask ResolveBinaryEx(BoundBinaryEx x, ConditionBranch branch)
12861286
case Operations.Spaceship:
12871287
return TypeCtx.GetLongTypeMask(); // -1, 0, +1
12881288

1289+
case Operations.Pipe:
1290+
return TypeRefMask.AnyType; // TODO: return value of the callback in R-Value
1291+
12891292
default:
12901293
throw ExceptionUtilities.UnexpectedValue(x.Operation);
12911294
}

src/Peachpie.CodeAnalysis/Semantics/Graph/BuilderVisitor.cs

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -802,21 +802,18 @@ public override void VisitJumpStmt(JumpStmt x)
802802
public override void VisitIfStmt(IfStmt x)
803803
{
804804
var end = NewBlock();
805-
806805
var conditions = x.Conditions;
807-
Debug.Assert(conditions.Length != 0);
806+
808807
BoundBlock elseBlock = null;
809-
for (int i = 0; i < conditions.Length; i++)
808+
foreach (var cond in conditions)
810809
{
811-
var cond = conditions[i];
812810
if (cond.Condition != null) // if (Condition) ...
813811
{
814-
elseBlock = (i == conditions.Length - 1) ? end : NewBlock();
812+
elseBlock = cond.Else == null ? end : NewBlock();
815813
_current = Connect(_current, NewBlock(), elseBlock, cond.Condition);
816814
}
817815
else // else ...
818816
{
819-
Debug.Assert(i != 0 && elseBlock != null);
820817
var body = elseBlock;
821818
elseBlock = end; // last ConditionalStmt
822819
_current = WithNewOrdinal(body);

src/Peachpie.CodeAnalysis/Semantics/SemanticsBinder.cs

Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -715,8 +715,6 @@ protected BoundExpression BindIncludeEx(AST.IncludingEx x)
715715
return new BoundIncludeEx(BindExpression(x.Target, BoundAccess.Read), x.InclusionType);
716716
}
717717

718-
protected BoundExpression BindConcatEx(AST.ConcatEx x) => BindConcatEx(x);
719-
720718
void BindConcatIntoList(List<BoundArgument> list, AST.Expression expr)
721719
{
722720
if (expr is AST.ConcatEx cex)
@@ -963,11 +961,23 @@ AST.Expression BindArm(AST.IExpression value, AST.MatchArm arm, AST.IExpression
963961
for (int i = 0; i < arm.ConditionList.Length; i++)
964962
{
965963
// value === condition[i]
966-
var cond = new AST.BinaryEx(arm.ConditionList[i].Span, AST.Operations.Identical, (AST.Expression)value, (AST.Expression)arm.ConditionList[i]) { ContainingElement = arm };
967-
968-
condition = condition == null
969-
? cond
970-
: new AST.BinaryEx(Span.Invalid, AST.Operations.Or, condition, cond) { ContainingElement = arm };
964+
var cond = AST.BinaryEx.Create(
965+
arm.ConditionList[i].Span,
966+
AST.Operations.Identical,
967+
(AST.Expression)value,
968+
(AST.Expression)arm.ConditionList[i])
969+
;
970+
cond.ContainingElement = arm;
971+
972+
if (condition == null)
973+
{
974+
condition = cond;
975+
}
976+
else
977+
{
978+
condition = AST.BinaryEx.Create(Span.Invalid, AST.Operations.Or, condition, cond);
979+
condition.ContainingElement = arm;
980+
}
971981
}
972982

973983
if (condition == null)
@@ -1329,6 +1339,16 @@ protected virtual BoundExpression BindBinaryEx(AST.BinaryEx expr)
13291339
laccess = BoundAccess.Read.WithQuiet(); // Template: A ?? B; // read A quietly
13301340
goto default;
13311341

1342+
case AST.Operations.Pipe:
1343+
// Template: A |> B;
1344+
// A: PhpValue
1345+
// B: IPhpoCallable
1346+
return new BoundBinaryEx(
1347+
BindExpression(expr.LeftExpr, laccess),
1348+
new BoundConvertToCallable(BindExpression(expr.RightExpr, BoundAccess.Read), this.DeclaringCompilation),
1349+
expr.Operation
1350+
);
1351+
13321352
default:
13331353
return new BoundBinaryEx(
13341354
BindExpression(expr.LeftExpr, laccess),

src/Peachpie.CodeAnalysis/Symbols/CoreMembers.cs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -902,10 +902,18 @@ public struct IPhpCallableHolder
902902
public IPhpCallableHolder(CoreTypes ct)
903903
{
904904
CoreTypes = ct;
905-
_Invoke_Context_PhpValueArray = null; // lazy
905+
906+
// lazy
907+
_Invoke_Context = null;
908+
_Invoke_Context_PhpValue = null;
909+
_Invoke_Context_PhpValueArray = null;
906910
//Invoke_Context_PhpValueArray = ct.IPhpCallable.Method("Invoke", ct.Context, ct.PhpValueArray);
907911
}
908912

913+
public MethodSymbol Invoke_Context => _Invoke_Context ??= CoreTypes.IPhpCallable.Method("Invoke", CoreTypes.Context).Symbol;
914+
915+
public MethodSymbol Invoke_Context_PhpValue => _Invoke_Context_PhpValue ??= CoreTypes.IPhpCallable.Method("Invoke", CoreTypes.Context, CoreTypes.PhpValue).Symbol;
916+
909917
public MethodSymbol Invoke_Context_PhpValueArray
910918
{
911919
get
@@ -927,6 +935,8 @@ public MethodSymbol Invoke_Context_PhpValueArray
927935
}
928936

929937
MethodSymbol
938+
_Invoke_Context,
939+
_Invoke_Context_PhpValue,
930940
_Invoke_Context_PhpValueArray;
931941
}
932942

src/Peachpie.CodeAnalysis/Syntax/PhpSyntaxTree.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ public class PhpSyntaxTree : SyntaxTree
8888
{ new Version(8, 2), LanguageFeatures.Php82Set },
8989
{ new Version(8, 3), LanguageFeatures.Php83Set },
9090
{ new Version(8, 4), LanguageFeatures.Php84Set },
91+
{ new Version(8, 5), LanguageFeatures.Php85Set },
9192
};
9293

9394
public static Version LatestLanguageVersion => SupportedLanguageVersions.Max();

0 commit comments

Comments
 (0)