From aef300a52c0fa366388b37a7e2d21629a05d8881 Mon Sep 17 00:00:00 2001 From: HAZAMA Date: Fri, 13 Jul 2018 01:16:22 +0900 Subject: [PATCH] we have passed EmitterTests.MatchStatements again --- Expresso/Analysis/TypeChecker.cs | 6 +- Expresso/Ast/Patterns/TuplePattern.cs | 10 ---- Expresso/CodeGen/CodeGenerator.cs | 56 ++++++++++++------- Expresso/CodeGen/ItemTypeInferencer.cs | 3 +- .../CodeGen/MatchClauseIdentifierDefiner.cs | 32 ++++++++--- 5 files changed, 64 insertions(+), 43 deletions(-) diff --git a/Expresso/Analysis/TypeChecker.cs b/Expresso/Analysis/TypeChecker.cs index dba5544..e48e574 100644 --- a/Expresso/Analysis/TypeChecker.cs +++ b/Expresso/Analysis/TypeChecker.cs @@ -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) @@ -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) diff --git a/Expresso/Ast/Patterns/TuplePattern.cs b/Expresso/Ast/Patterns/TuplePattern.cs index f919164..5e4a15d 100755 --- a/Expresso/Ast/Patterns/TuplePattern.cs +++ b/Expresso/Ast/Patterns/TuplePattern.cs @@ -16,16 +16,6 @@ public class TuplePattern : PatternConstruct /// public AstNodeCollection Patterns => GetChildrenByRole(Roles.Pattern); - /// - /// Represents the resolved type as . - /// Will be resolved in - /// - /// The type of the resolved. - public SimpleType ResolvedType{ - get => GetChildByRole(Roles.GenericType); - set => SetChildByRole(Roles.GenericType, value); - } - public TuplePattern(IEnumerable patterns) : base(patterns.First().StartLocation, patterns.Last().EndLocation) { diff --git a/Expresso/CodeGen/CodeGenerator.cs b/Expresso/CodeGen/CodeGenerator.cs index 463539b..9e7bb8f 100755 --- a/Expresso/CodeGen/CodeGenerator.cs +++ b/Expresso/CodeGen/CodeGenerator.cs @@ -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; @@ -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) @@ -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); @@ -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); @@ -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}); @@ -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 @@ -2216,6 +2223,8 @@ public Type VisitDestructuringPattern(DestructuringPattern destructuringPattern, var block = new List(); var block_params = new List(); + 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) @@ -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().ToList(); + /*if(context.Additionals.Any()){ + var block_contents = context.Additionals.OfType().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)); @@ -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(); var block = new List(); 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) @@ -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); @@ -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)); @@ -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) diff --git a/Expresso/CodeGen/ItemTypeInferencer.cs b/Expresso/CodeGen/ItemTypeInferencer.cs index 3c1ad53..31a1881 100644 --- a/Expresso/CodeGen/ItemTypeInferencer.cs +++ b/Expresso/CodeGen/ItemTypeInferencer.cs @@ -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) diff --git a/Expresso/CodeGen/MatchClauseIdentifierDefiner.cs b/Expresso/CodeGen/MatchClauseIdentifierDefiner.cs index 7a26130..6053314 100644 --- a/Expresso/CodeGen/MatchClauseIdentifierDefiner.cs +++ b/Expresso/CodeGen/MatchClauseIdentifierDefiner.cs @@ -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); } } @@ -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) @@ -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) @@ -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); }