Skip to content

Commit

Permalink
we have passed EmitterTests.MatchStatements again
Browse files Browse the repository at this point in the history
  • Loading branch information
HAZAMA committed Jul 12, 2018
1 parent 4bd421c commit aef300a
Show file tree
Hide file tree
Showing 5 changed files with 64 additions and 43 deletions.
6 changes: 2 additions & 4 deletions Expresso/Analysis/TypeChecker.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1681,9 +1681,7 @@ public AstType VisitTuplePattern(TuplePattern tuplePattern)
from p in tuplePattern.Patterns
select p.AcceptWalker(this).Clone();
// TODO: consider the case that the tuple contains an IgnoringRestPattern
var tuple_type = AstType.MakeSimpleType("tuple", types, tuplePattern.StartLocation, tuplePattern.EndLocation);
tuplePattern.ResolvedType = tuple_type;
return tuple_type;
return AstType.MakeSimpleType("tuple", types, tuplePattern.StartLocation, tuplePattern.EndLocation);
}

public AstType VisitExpressionPattern(ExpressionPattern exprPattern)
Expand All @@ -1693,7 +1691,7 @@ public AstType VisitExpressionPattern(ExpressionPattern exprPattern)

public AstType VisitIgnoringRestPattern(IgnoringRestPattern restPattern)
{
return AstType.MakePlaceholderType();
return SimpleType.Null;
}

public AstType VisitKeyValuePattern(KeyValuePattern keyValuePattern)
Expand Down
10 changes: 0 additions & 10 deletions Expresso/Ast/Patterns/TuplePattern.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,6 @@ public class TuplePattern : PatternConstruct
/// </summary>
public AstNodeCollection<PatternConstruct> Patterns => GetChildrenByRole(Roles.Pattern);

/// <summary>
/// Represents the resolved type as <see cref="SimpleType"/>.
/// Will be resolved in <see cref="Analysis.TypeChecker"/>
/// </summary>
/// <value>The type of the resolved.</value>
public SimpleType ResolvedType{
get => GetChildByRole(Roles.GenericType);
set => SetChildByRole(Roles.GenericType, value);
}

public TuplePattern(IEnumerable<PatternConstruct> patterns)
: base(patterns.First().StartLocation, patterns.Last().EndLocation)
{
Expand Down
56 changes: 35 additions & 21 deletions Expresso/CodeGen/CodeGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -607,7 +607,7 @@ public Type VisitMatchStatement(MatchStatement matchStmt, CSharpEmitterContext c
var tmp_var = il_generator.DeclareLocal(target_type);
EmitSet(null, tmp_var, -1, null);

var parameters = ExpandTuple(target_type, tmp_var);
//var parameters = ExpandTuple(target_type, tmp_var);
context.TemporaryVariable = tmp_var;
context.ContextExpression = null;
var context_ast = context.ContextAst;
Expand Down Expand Up @@ -637,7 +637,7 @@ public Type VisitMatchStatement(MatchStatement matchStmt, CSharpEmitterContext c
context.TemporaryVariable = null;
context.ContextAst = context_ast;

return null;//CSharpExpr.Block(parameters, block_contents);
return null;
}

public Type VisitThrowStatement(ThrowStatement throwStmt, CSharpEmitterContext context)
Expand Down Expand Up @@ -1562,6 +1562,8 @@ public Type VisitMatchClause(MatchPatternClause matchClause, CSharpEmitterContex
var res = matchClause.Patterns.First().AcceptWalker(this, context);

// Emit conditions
var prev_op_type = context.OperationTypeOnIdentifier;
context.OperationTypeOnIdentifier = OperationType.Load;
matchClause.Patterns.First().AcceptWalker(condition_definer);
foreach(var pattern in matchClause.Patterns.Skip(1)){
il_generator.Emit(OpCodes.Brtrue, context.CurrentOrTargetLabel);
Expand All @@ -1581,9 +1583,11 @@ public Type VisitMatchClause(MatchPatternClause matchClause, CSharpEmitterContex

var guard = matchClause.Guard.AcceptWalker(this, context);

il_generator.Emit(OpCodes.Brfalse, context.CurrentAndTargetLabel);
if(!(matchClause.Patterns.First() is WildcardPattern))
il_generator.Emit(OpCodes.Brfalse, context.CurrentAndTargetLabel);

il_generator.MarkLabel(context.CurrentOrTargetLabel);
context.OperationTypeOnIdentifier = prev_op_type;
matchClause.Body.AcceptWalker(this, context);

il_generator.Emit(OpCodes.Br, context.CurrentJumpLabel);
Expand Down Expand Up @@ -2079,7 +2083,7 @@ public Type VisitIdentifierPattern(IdentifierPattern identifierPattern, CSharpEm
{
// An identifier pattern can arise by itself or as a child
Type type = null;
if(!(context.ContextAst is MatchStatement)){
//if(!(context.ContextAst is MatchStatement)){
type = RetrieveType(identifierPattern.Identifier.Type);
var local_builder = il_generator.DeclareLocal(type);
AddSymbol(identifierPattern.Identifier, new ExpressoSymbol{LocalBuilder = local_builder});
Expand All @@ -2090,16 +2094,19 @@ public Type VisitIdentifierPattern(IdentifierPattern identifierPattern, CSharpEm
if(context.OperationTypeOnIdentifier == OperationType.Set)
EmitSet(null, local_builder, -1, null);

if(context.ContextAst is MatchStatement)
context.CurrentTargetVariable = local_builder;

var start_loc = identifierPattern.Identifier.StartLocation;
var end_loc = identifierPattern.Identifier.EndLocation;
//il_generator.MarkSequencePoint();
//var debug_info = CSharpExpr.DebugInfo(document_info, start_loc.Line, start_loc.Column, end_loc.Line, end_loc.Column);
}else{
/*}else{
var prev_op_type = context.OperationTypeOnIdentifier;
context.OperationTypeOnIdentifier = OperationType.None;
type = VisitIdentifier(identifierPattern.Identifier, context);
context.OperationTypeOnIdentifier = prev_op_type;
}
}*/

if(identifierPattern.Parent is MatchPatternClause){
// Set context.ContextExpression to a block
Expand Down Expand Up @@ -2216,6 +2223,8 @@ public Type VisitDestructuringPattern(DestructuringPattern destructuringPattern,

var block = new List<CSharpExpr>();
var block_params = new List<ExprTree.ParameterExpression>();
var prev_op_type = context.OperationTypeOnIdentifier;
context.OperationTypeOnIdentifier = OperationType.None;
foreach(var pattern in destructuringPattern.Items){
var item_ast_type = pattern.AcceptWalker(item_type_inferencer);
if(item_ast_type == null)
Expand Down Expand Up @@ -2247,25 +2256,27 @@ public Type VisitDestructuringPattern(DestructuringPattern destructuringPattern,
}else{
var field = (FieldInfo)context.PropertyOrField;
context.PropertyOrField = null;
EmitLoadLocal(context.TemporaryVariable, false);
EmitLoadField(field);

if(context.CurrentTargetVariable != null){
EmitSet(null, context.CurrentTargetVariable, -1, null);
context.CurrentTargetVariable = null;
}else{
if(context.Additionals.Any()){
/*var block_contents = context.Additionals.OfType<CSharpExpr>().ToList();
/*if(context.Additionals.Any()){
var block_contents = context.Additionals.OfType<CSharpExpr>().ToList();
if(expr != null){
var if_content = CSharpExpr.IfThen(expr, context.ContextExpression);
block_contents.Add(if_content);
}
context.ContextExpression = CSharpExpr.Block(context.AdditionalParameters, block_contents);*/
}else{
context.ContextExpression = CSharpExpr.Block(context.AdditionalParameters, block_contents);
}else{*/
EmitBinaryOpInMiddle(OperatorType.ConditionalAnd, context);
}
//}
}
}
}
context.OperationTypeOnIdentifier = prev_op_type;

/*if(res != null)
block.Add(CSharpExpr.IfThen(res, context.ContextExpression));
Expand All @@ -2283,11 +2294,12 @@ public Type VisitTuplePattern(TuplePattern tuplePattern, CSharpEmitterContext co
{
// Tuple patterns should always be combined with value binding patterns
if(tuplePattern.Ancestors.Any(a => a is MatchStatement)){
var tuple_type = item_type_inferencer.VisitTuplePattern(tuplePattern);
var native_tuple_type = CSharpCompilerHelpers.GetNativeType(tuple_type);
var native_tuple_type = context.TemporaryVariable.LocalType;
var block_params = new List<ExprTree.ParameterExpression>();
var block = new List<CSharpExpr>();
int i = 1;
var prev_op_type = context.OperationTypeOnIdentifier;
context.OperationTypeOnIdentifier = OperationType.None;
foreach(var pattern in tuplePattern.Patterns){
var item_ast_type = pattern.AcceptWalker(item_type_inferencer);
if(item_ast_type == null)
Expand All @@ -2297,6 +2309,7 @@ public Type VisitTuplePattern(TuplePattern tuplePattern, CSharpEmitterContext co
//var tmp_param = CSharpExpr.Parameter(item_type, "__" + VariableCount++);
var prop_name = "Item" + i++;
var property = native_tuple_type.GetProperty(prop_name);
EmitLoadLocal(context.TemporaryVariable, false);
EmitCall(property.GetMethod);
//var assignment = CSharpExpr.Assign(tmp_param, property_access);
//context.Additionals.Add(assignment);
Expand Down Expand Up @@ -2328,6 +2341,7 @@ public Type VisitTuplePattern(TuplePattern tuplePattern, CSharpEmitterContext co
}*/
}
}
context.OperationTypeOnIdentifier = prev_op_type;

/*if(res != null)
block.Add(CSharpExpr.IfThen(res, context.ContextExpression));
Expand All @@ -2348,24 +2362,24 @@ public Type VisitTuplePattern(TuplePattern tuplePattern, CSharpEmitterContext co

public Type VisitExpressionPattern(ExpressionPattern exprPattern, CSharpEmitterContext context)
{
// Common scinario in an expression pattern:
// An integer sequence expression or a literal expression.
// In the former case we should test an integer against an IntSeq type object using an IntSeq's method
// while in the latter case we should just test the value against the literal
context.RequestMethod = true;
/*context.RequestMethod = true;
context.Method = null;
var type = exprPattern.Expression.AcceptWalker(this, context);
context.RequestMethod = false;
if(context.Method != null && context.Method.DeclaringType.Name == "ExpressoIntegerSequence"){
il_generator.Emit(OpCodes.Callvirt, context.Method);
var method = context.Method;
context.Method = null;
il_generator.Emit(OpCodes.Callvirt, method);
return null;
}else if(context.ContextAst is MatchStatement){
EmitLoadLocal(context.TemporaryVariable, false);
il_generator.Emit(OpCodes.Ceq);
return null;
return type;
}else{
return type;
}
}*/
return null;
}

public Type VisitIgnoringRestPattern(IgnoringRestPattern restPattern, CSharpEmitterContext context)
Expand Down
3 changes: 2 additions & 1 deletion Expresso/CodeGen/ItemTypeInferencer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -382,7 +382,8 @@ public AstType VisitTryStatement(TryStatement tryStmt)

public AstType VisitTuplePattern(TuplePattern tuplePattern)
{
return tuplePattern.ResolvedType;
var item_types = tuplePattern.Patterns.Select(pat => pat.AcceptWalker(this));
return AstType.MakeSimpleType("tuple", item_types);
}

public AstType VisitTypeConstraint(TypeConstraint constraint)
Expand Down
32 changes: 25 additions & 7 deletions Expresso/CodeGen/MatchClauseIdentifierDefiner.cs
Original file line number Diff line number Diff line change
Expand Up @@ -119,13 +119,14 @@ public void VisitDestructuringPattern(DestructuringPattern destructuringPattern)
var variant_name = ((MemberType)destructuringPattern.TypePath).ChildType.Name;
var field = context.TargetType.GetField(HiddenMemberPrefix + variant_name);
generator.EmitLoadField(field);
generator.EmitObject(null);
generator.il_generator.Emit(OpCodes.Ldnull);
generator.EmitBinaryOp(OperatorType.InEquality);
}else{
var native_type = CSharpCompilerHelpers.GetNativeType(destructuringPattern.TypePath);
generator.EmitLoadLocal(context.TemporaryVariable, false);
generator.il_generator.Emit(OpCodes.Isinst, native_type);
generator.EmitObject(null);
generator.EmitBinaryOp(OperatorType.Equality);
generator.il_generator.Emit(OpCodes.Ldnull);
generator.EmitBinaryOp(OperatorType.InEquality);
}
}

Expand All @@ -141,6 +142,25 @@ public void VisitEmptyStatement(EmptyStatement emptyStmt)

public void VisitExpressionPattern(ExpressionPattern exprPattern)
{
// Common scinario in an expression pattern:
// An integer sequence expression or a literal expression.
// In the former case we should test an integer against an IntSeq type object using an IntSeq's method
// while in the latter case we should just test the value against the literal
context.RequestMethod = true;
context.Method = null;
var type = exprPattern.Expression.AcceptWalker(generator, context);
context.RequestMethod = false;

if(context.Method != null && context.Method.DeclaringType.Name == "ExpressoIntegerSequence"){
var method = context.Method;
context.Method = null;

generator.EmitLoadLocal(context.TemporaryVariable, false);
generator.il_generator.Emit(OpCodes.Callvirt, method);
}else if(context.ContextAst is MatchStatement){
generator.EmitLoadLocal(context.TemporaryVariable, false);
generator.il_generator.Emit(OpCodes.Ceq);
}
}

public void VisitExpressionStatement(ExpressionStatement exprStmt)
Expand Down Expand Up @@ -185,11 +205,9 @@ public void VisitIdentifier(Identifier ident)

public void VisitIdentifierPattern(IdentifierPattern identifierPattern)
{
/*var native_type = CSharpCompilerHelpers.GetNativeType(identifierPattern.Identifier.Type);
var native_param = System.Linq.Expressions.Expression.Parameter(native_type, identifierPattern.Identifier.Name);
AddSymbol(identifierPattern.Identifier, new ExpressoSymbol{Parameter = native_param});*/
var symbol = generator.GetRuntimeSymbol(identifierPattern.Identifier);
context.CurrentTargetVariable = symbol.LocalBuilder;
identifierPattern.InnerPattern.AcceptWalker(this);
}

public void VisitIfStatement(IfStatement ifStmt)
Expand Down Expand Up @@ -368,7 +386,7 @@ public void VisitTryStatement(TryStatement tryStmt)

public void VisitTuplePattern(TuplePattern tuplePattern)
{
var tuple_type = CSharpCompilerHelpers.GetNativeType(tuplePattern.ResolvedType);
var tuple_type = context.TemporaryVariable.LocalType;
generator.EmitLoadLocal(context.TemporaryVariable, false);
generator.il_generator.Emit(OpCodes.Isinst, tuple_type);
}
Expand Down

0 comments on commit aef300a

Please sign in to comment.