public void TestInheritance() { var dbContextClassDefinition = new ClassDefinition { Name = "StoreDbContext", BaseClass = "Microsoft.EntityFrameworkCore.DbContext" }; var repositoryInterfaceDefinition = new InterfaceDefinition { Name = "ISalesRepository", Implements = { "IRepository" } }; var savingTypeEnum = new EnumDefinition { Name = "SavingType", BaseType = "int" }; Assert.True(dbContextClassDefinition.HasInheritance); Assert.True(dbContextClassDefinition.BaseClass != null); Assert.True(dbContextClassDefinition.Implements.Count == 0); Assert.True(repositoryInterfaceDefinition.HasInheritance); Assert.False(repositoryInterfaceDefinition.Implements.Count == 0); Assert.True(savingTypeEnum.HasInheritance); }
private void ParseInterface(AccessLevel accessLevel) { Token interfaceKeyword = _lexer.Eat(TokenType.InterfaceKeyword); Token name = _lexer.Eat(TokenType.Identifer); if (accessLevel != AccessLevel.Public) { accessLevel = AnalysisAccessLevel(name.Content); } Token colon = null, inheritanceToken = null; if (_lexer.Match(":")) { colon = _lexer.Eat(TokenType.Colon); inheritanceToken = _lexer.Eat(TokenType.Identifer); } InterfaceDefinition interfaceDefinition = new InterfaceDefinition(interfaceKeyword, name, colon, inheritanceToken, _endNameSpace, accessLevel); _endNameSpace.AddStructure(interfaceDefinition); FilesDefinitions[_lexer.FileIndex].Add(interfaceDefinition); _parsingStructure = interfaceDefinition; ParseChunk(s_interfaceDefinitionOrder, out Token openBrace, out Token closeBrace); interfaceDefinition.SetBraces(openBrace, closeBrace); _parsingStructure = null; }
public override AstNode Visit(InterfaceDefinition node) { // Use the generic scope. PseudoScope genScope = node.GetGenericScope(); if (genScope != null) { PushScope(genScope); } // Process the base structures. ProcessBases(node); // Update the scope. PushScope(node.GetScope()); // Visit his children. VisitList(node.GetChildren()); // Restore the scope. PopScope(); // Pop the generic scope. if (genScope != null) { PopScope(); } return(node); }
private static List <InterfaceDefinition> GetExistingServiceContractDefinitions(string serviceContractsFolder, ref GenResult result, List <string> exclusions = null) { var syncInterfaceFiles = Directory.GetFiles(serviceContractsFolder, "I*.*"); var interfacesToCreate = new List <InterfaceDefinition>(); foreach (var syncInterface in syncInterfaceFiles) { var fi = new FileInfo(syncInterface); var fileName = fi.Name; var isExcluded = exclusions != null && exclusions.Any(e => e.Equals(fileName, StringComparison.OrdinalIgnoreCase)); if (isExcluded) { result.Debug($"Skipping file {syncInterface}"); continue; } var serviceContractName = Path.GetFileNameWithoutExtension(fileName); result.Debug($"Building definition for {serviceContractName} from {fileName}"); var idef = new InterfaceDefinition(serviceContractName, fi.FullName) { ExistingServiceContractSyntaxTree = CSharpSyntaxTree.ParseText(File.ReadAllText(fi.FullName)) }; result.Debug($"Info definition {Environment.NewLine} {idef}"); interfacesToCreate.Add(idef); } return(interfacesToCreate); }
public async Task Should_fail_if_ActualType_is_not_possible() { /* Given */ var schema = await new SchemaBuilder() .Add(@" interface Character type Human type Query ").Build(new SchemaBuildOptions()); InterfaceDefinition character = "interface Character"; ObjectDefinition humanNotCharacter = "type Human"; var value = new object(); var context = Substitute.For <IResolverContext>(); context.ExecutionContext.Schema.Returns(schema); context.FieldName.Returns("field"); context.Field.Returns("field: Character"); var sut = new CompleteValueResult(value, humanNotCharacter); /* When */ var exception = await Assert.ThrowsAsync <CompleteValueException>(() => sut.CompleteValueAsync(context).AsTask()); /* Then */ Assert.Equal( "Cannot complete value for field 'field: Character'. ActualType 'Human' does not implement interface 'Character'", exception.Message); }
public override Object Visit(InterfaceDefinition node, Object obj) { for (int i = 0; i < node.BaseClass.Count; i++) { TypeExpression typeExpression = this.searchType(node.BaseClass[i], node.Location.Line, node.Location.Column); if (typeExpression == null) { ErrorManager.Instance.NotifyError(new UnknownTypeError(node.BaseClass[i], node.Location)); } else { InterfaceType interfaze = typeExpression as InterfaceType; if (interfaze == null) { ErrorManager.Instance.NotifyError(new ExpectedInterfaceError(node.BaseClass[i], node.Location)); } else { ((InterfaceType)node.TypeExpr).AddBaseInterface(interfaze, node.Location); } } } ((InterfaceType)node.TypeExpr).Members = builtClass(node, obj); node.TypeExpr.BuildTypeExpressionString(TypeExpression.MAX_DEPTH_LEVEL_TYPE_EXPRESSION); return(null); }
public void TestInterface1() { Boo.Lang.Compiler.Ast.Module module = ParseTestCase("interface_1.boo"); Assert.AreEqual(1, module.Members.Count); InterfaceDefinition id = (InterfaceDefinition)module.Members[0]; Assert.AreEqual("IContentItem", id.Name); Assert.AreEqual(5, id.Members.Count); Property p = (Property)id.Members[0]; Assert.AreEqual("Parent", p.Name); Assert.AreEqual("IContentItem", ((SimpleTypeReference)p.Type).Name); Assert.IsNotNull(p.Getter, "Getter"); Assert.IsNull(p.Setter, "Setter"); p = (Property)id.Members[1]; Assert.AreEqual("Name", p.Name); Assert.AreEqual("string", ((SimpleTypeReference)p.Type).Name); Assert.IsNotNull(p.Getter, "Getter"); Assert.IsNotNull(p.Setter, "Setter"); Method m = (Method)id.Members[2]; Assert.AreEqual("SelectItem", m.Name); Assert.AreEqual("IContentItem", ((SimpleTypeReference)m.ReturnType).Name); Assert.AreEqual("expression", m.Parameters[0].Name); Assert.AreEqual("string", ((SimpleTypeReference)m.Parameters[0].Type).Name); Assert.AreEqual("Validate", ((Method)id.Members[3]).Name); Assert.AreEqual("OnRemove", ((Method)id.Members[4]).Name); }
override public void LeaveInterfaceDefinition(InterfaceDefinition node) { CheckMemberName(node); CantBeMarkedAbstract(node); CantBeMarkedTransient(node); CantBeMarkedPartial(node); }
override public void OnInterfaceDefinition(InterfaceDefinition node) { if (null != node.Entity) { return; } node.Entity = new InternalInterface(TypeSystemServices, node); }
protected override void EnterInterfaceDefinition(PrinterContext context, InterfaceDefinition interfaceDefinition) { context.Append(' '); context.AppendDescription(interfaceDefinition.Description); context.Append("interface "); context.Append(interfaceDefinition.Name); context.Append(" "); }
override public void LeaveInterfaceDefinition(InterfaceDefinition node) { CantBeMarkedAbstract(node); CantBeMarkedTransient(node); CantBeMarkedPartialIfNested(node); CantBeMarkedFinal(node); CantBeMarkedStatic(node); }
internal static RedwoodType Make(InterfaceDefinition @interface) { RedwoodType type = new RedwoodType(); type.Name = @interface.Name; type.IsInterface = true; return(type); }
public override void Switch(IAstTransformer transformer, out Node resultingNode) { InterfaceDefinition thisNode = (InterfaceDefinition)this; InterfaceDefinition resultingTypedNode = thisNode; transformer.OnInterfaceDefinition(thisNode, ref resultingTypedNode); resultingNode = resultingTypedNode; }
public IEnumerable<TypeDefinition> GetPossibleTypes(InterfaceDefinition abstractType) { foreach (var objectDefinition in QueryTypes<ObjectDefinition>(ob => ob.HasInterface(abstractType.Name))) yield return objectDefinition; foreach (var interfaceDefinition in QueryTypes<InterfaceDefinition>(ob => ob.HasInterface(abstractType.Name))) yield return interfaceDefinition; }
public async Task GenericConstraintsReturnsEmptyWhenNoConstraintsDeclared() { var node = await TestNode.FindNode <InterfaceDeclarationSyntax>(TypeDefinitionCode.InterfaceWithoutParent) .ConfigureAwait(false); var actual = new InterfaceDefinition(node); actual.GenericConstraints.Should().BeEmpty(); }
public override Object Visit(InterfaceDefinition node, Object obj) { for (int i = 0; i < node.MemberCount; i++) { node.GetMemberElement(i).Accept(this, obj); } return(null); }
public override object Visit(InterfaceDefinition node, object obj) { if (node.Location == ((AstNode)obj).Location || found) { found = true; return(this.table); } return(base.Visit(node, obj)); }
internal static UserDefinedType CreateInterface(BaseTypeDeclarationSyntax node, ISyntaxEntity parent, CodeFile currentCodeFile, SyntaxTree tree) { UserDefinedType typeObj = new InterfaceDefinition(node.Identifier.Text, new FileSpan(tree.GetLineSpan(node.Span)), parent, currentCodeFile); processModifiers(typeObj, node.Modifiers); typeObj.AccessSpecifiers = typeObj.AccessSpecifiers == AccessSpecifiers.None ? AccessSpecifiers.Internal : typeObj.AccessSpecifiers; typeObj.AssociatedComment = GetComment(typeObj, node, tree, currentCodeFile); return(typeObj); }
public override void OnInterfaceDefinition(InterfaceDefinition node) { if (WasVisited(node)) { return; } MarkVisited(node); base.OnInterfaceDefinition(node); }
private void VisitInterfaceDefinition(InterfaceDefinition node) { EnterNode(node); Visit(node.Interfaces); Visit(node.Directives); Visit(node.Fields); ExitNode(node); }
private void ExtractInterface(Cci.INamedTypeDefinition typedef) { var name = typedef.Name.Value; var type = new InterfaceDefinition(name); this.ExtractGenericParameters(type.GenericParameters, typedef.GenericParameters); this.ExtractInterfaces(type.Interfaces, typedef.Interfaces); this.ExtractMethods(type.Methods, typedef.Methods); types.Add(name, type); }
void CheckInterfaceBaseTypes(InterfaceDefinition node) { foreach (TypeReference baseType in node.BaseTypes) { IType tag = GetType(baseType); if (!tag.IsInterface) { Error(CompilerErrorFactory.InterfaceCanOnlyInheritFromInterface(baseType, node.FullName, tag.FullName)); } } }
void CheckInterfaceBaseTypes(InterfaceDefinition node) { foreach (var baseTypeRef in node.BaseTypes) { var baseType = GetType(baseTypeRef); if (!baseType.IsInterface) { Error(CompilerErrorFactory.InterfaceCanOnlyInheritFromInterface(baseTypeRef, GetType(node), baseType)); } } }
public async Task ModifiersReturnsExpectedValue(string modifiers, InterfaceModifiers expected) { var code = TypeDefinitionCode.EmptyInterface.Replace("public interface MyInterface", "public " + modifiers + " interface MyInterface"); var node = await TestNode.FindNode <InterfaceDeclarationSyntax>(code) .ConfigureAwait(false); var sut = new InterfaceDefinition(node); sut.Modifiers.Should().Be(expected); }
public async Task CanCreateFromDeclarationNode() { var node = await TestNode.FindNode <InterfaceDeclarationSyntax>(TypeDefinitionCode.EmptyInterface) .ConfigureAwait(false); var sut = new InterfaceDefinition(node); sut.Name.Should().Be("MyInterface"); sut.Namespace.Should().Be("MyNamespace"); sut.DeclaringType.Should().BeNull(); sut.ChildClasses.Should().BeEmpty(); }
public static bool TryGetDirective( this InterfaceDefinition definition, Name directiveName, [NotNullWhen(true)] out Directive?directive) { if (definition.Directives is null) { directive = null; return(false); } return(definition.Directives.TryGet(directiveName, out directive)); }
public void WithDescription() { /* Given */ InterfaceDefinition original = @"interface Inf"; /* When */ var modified = original .WithDescription("Description"); /* Then */ Assert.Null(original.Description); Assert.Equal("Description", modified.Description); }
public void FromString() { /* Given */ /* When */ InterfaceDefinition original = @"interface Inf { field1: String }"; /* Then */ Assert.Equal("Inf", original.Name); Assert.NotNull(original.Fields); }
public void WithName() { /* Given */ InterfaceDefinition original = @"interface Inf"; /* When */ var modified = original .WithName("Renamed"); /* Then */ Assert.Equal("Inf", original.Name); Assert.Equal("Renamed", modified.Name); }
public void FromBytes() { /* Given */ /* When */ InterfaceDefinition original = Encoding.UTF8.GetBytes(@"interface Inf { field1: String }").AsReadOnlySpan(); /* Then */ Assert.Equal("Inf", original.Name); Assert.NotNull(original.Fields); }
internal object Interpret(AstNode inputNode, CodeContext context) { AstNode node = inputNode; //The next node to be evaluated var flow_manager = new InterpreterFlowManager(); try{ while(true){ MAIN_LOOP: //sub-expressionを評価する必要があるノードの飛び先 switch(node.Type){ case NodeType.Argument: node = ((ParameterDeclaration)node).Option; goto MAIN_LOOP; case NodeType.Assignment: { var assignment = (AssignmentExpression)node; if(!flow_manager.IsEvaluating(assignment)){ //まず右辺値を評価する flow_manager.Push(assignment); node = assignment.Right; goto MAIN_LOOP; }else{ flow_manager.Pop(); ExpressoTuple rhs = (ExpressoTuple)flow_manager.PopValue(); for(int i = 0; i < assignment.Left.Length; ++i){ //その後左辺値に代入する var seq = (SequenceExpression)assignment.Left[i]; for(int j = 0; j < rhs.Count; ++j){ var assignable = seq.Items[j] as Assignable; if(assignable == null) throw ExpressoOps.MakeRuntimeError("{0} is not an assignable reference.", seq.Items[j]); assignable.Assign(flow_manager.Top(), rhs[j]); } } } break; } case NodeType.BinaryExpression: { var binary_op = (BinaryExpression)node; if(!flow_manager.IsEvaluating(binary_op)) flow_manager.Push(binary_op); switch(flow_manager.Top().StepCounter){ case 0: node = binary_op.Left; flow_manager.Top().StepCounter++; goto MAIN_LOOP; case 1: node = binary_op.Right; flow_manager.Top().StepCounter++; goto MAIN_LOOP; case 2: flow_manager.Pop(); object rhs = flow_manager.PopValue(), lhs = flow_manager.PopValue(); if(lhs == null || rhs == null) throw ExpressoOps.MakeRuntimeError("Can not apply the operation on null objects."); object ret = null; if((int)binary_op.Operator <= (int)OperatorType.Modulus){ if(lhs is int) ret = BinaryExprAsInt((int)lhs, (int)rhs, binary_op.Operator); else if(lhs is double) ret = BinaryExprAsDouble((double)lhs, (double)rhs, binary_op.Operator); else if(lhs is Fraction) ret = BinaryExprAsFraction((Fraction)lhs, rhs, binary_op.Operator); else ret = BinaryExprAsString((string)lhs, rhs, binary_op.Operator); }else if((int)binary_op.Operator < (int)OperatorType.ConditionalAnd){ ret = EvalComparison(lhs as IComparable, rhs as IComparable, binary_op.Operator); }else if((int)binary_op.Operator < (int)OperatorType.BitwiseOr){ ret = EvalLogicalOperation((bool)lhs, (bool)rhs, binary_op.Operator); }else{ ret = EvalBitOperation((int)lhs, (int)rhs, binary_op.Operator); } flow_manager.PushValue(ret); break; } break; } case NodeType.Block: { var block = (BlockStatement)node; if(!flow_manager.IsEvaluating(block)) flow_manager.Push(block); if(flow_manager.Top().ChildCounter < block.Statements.Count){ node = block.Statements[flow_manager.Top().ChildCounter++]; goto MAIN_LOOP; }else{ flow_manager.Pop(); } break; } case NodeType.BreakStatement: { var break_stmt = (BreakStatement)node; for(int i = break_stmt.Count; i > 0;){ //Count階層分ループを遡るまで出会ったbreakableをノードスタックから取り除く AstNode popped = flow_manager.Pop().TargetNode; if(popped.Type == NodeType.ForStatement || popped.Type == NodeType.WhileStatement) --i; } break; } case NodeType.Call: { var call = (CallExpression)node; if(!flow_manager.IsEvaluating(call)) flow_manager.Push(call); switch(flow_manager.Top().StepCounter){ case 0: node = call.Target; flow_manager.Top().StepCounter++; goto MAIN_LOOP; case 1: var fn = flow_manager.Top().Get(0) as FunctionDeclaration; if(flow_manager.Top().ChildCounter < fn.Parameters.Length){ //実引数を評価してスタックに積む var index = flow_manager.Top().ChildCounter++; var param = fn.Parameters[index]; node = (index < call.Arguments.Length) ? call.Arguments[index] : param; goto MAIN_LOOP; } flow_manager.Top().Remove(0); //呼び出す関数オブジェクトをスタックから除く node = fn.Body; flow_manager.Top().StepCounter = fn.HasReturn ? 2 : 3; goto MAIN_LOOP; case 2: var ret = flow_manager.PopValue(); flow_manager.Top().Clear(); //関数呼び出しに使ったスタック領域を解放する flow_manager.PushValue(ret); flow_manager.Pop(); break; case 3: flow_manager.Top().Clear(); //関数呼び出しに使ったスタック領域を解放する flow_manager.Pop(); break; } break; } case NodeType.CaseClause: { var case_clause = (MatchPatternClause)node; if(!flow_manager.IsEvaluating(case_clause)) flow_manager.Push(case_clause); switch(flow_manager.Top().StepCounter){ case 0: if(flow_manager.Top().ChildCounter < case_clause.Patterns.Length){ node = case_clause.Patterns[flow_manager.Top().ChildCounter++]; goto MAIN_LOOP; }else{ flow_manager.PushValue(false); flow_manager.Pop(); } break; case 1: var label_obj = flow_manager.PopValue(); var target = flow_manager.TopValue(); if(target is int && label_obj is ExpressoIntegerSequence){ var int_seq = (ExpressoIntegerSequence)label_obj; if(int_seq.Includes((int)target)){ node = case_clause.Body; flow_manager.Top().StepCounter++; goto MAIN_LOOP; }else{ flow_manager.Top().StepCounter--; } }else if(label_obj is LiteralExpression && ((LiteralExpression)label_obj).Type == ObjectTypes._CASE_DEFAULT){ node = case_clause.Body; flow_manager.Top().StepCounter++; goto MAIN_LOOP; }else if(label_obj != null && label_obj.Equals(target)){ node = case_clause.Body; flow_manager.Top().StepCounter++; goto MAIN_LOOP; }else{ flow_manager.Top().StepCounter--; } break; case 2: flow_manager.Pop(); flow_manager.PushValue(true); break; } break; } case NodeType.CastExpression: { var cast_expr = (CastExpression)node; if(!flow_manager.IsEvaluating(cast_expr)) flow_manager.Push(cast_expr); switch(flow_manager.Top().StepCounter){ case 0: node = cast_expr.Target; flow_manager.Top().StepCounter++; goto MAIN_LOOP; case 1: node = cast_expr.ToExpression; flow_manager.Top().StepCounter++; goto MAIN_LOOP; case 2: flow_manager.Pop(); var to_expr = flow_manager.PopValue(); var target = flow_manager.PopValue(); break; } break; } case NodeType.CatchClause: { var catch_clause = (CatchClause)node; var exception = flow_manager.TopValue() as ExpressoThrowException; if(exception == null){ throw ExpressoOps.MakeSystemError("The top value of stack is not an exception."); }else if(catch_clause.Catcher.ParamType.TypeName == exception.Thrown.Name){ node = catch_clause.Body; goto case NodeType.Block; } break; } case NodeType.Comprehension: //TODO:実装する { break; } case NodeType.ComprehensionFor: { break; } case NodeType.ComprehensionIf: { var comp_if = (ComprehensionIfClause)node; if(!flow_manager.IsEvaluating(comp_if)) flow_manager.Push(comp_if); switch(flow_manager.Top().StepCounter){ case 0: node = comp_if.Condition; flow_manager.Top().StepCounter++; goto MAIN_LOOP; case 1: var cond = flow_manager.TopValue(); if(!(cond is bool)) throw ExpressoOps.MakeInvalidTypeError("Can not evaluate the expression to a boolean."); if((bool)cond){ var yield_expr = flow_manager.Top().Get(0) as Expression; node = (comp_if.Body == null) ? yield_expr : comp_if.Body; flow_manager.Pop(); goto MAIN_LOOP; }else{ flow_manager.Pop(); } break; } break; } case NodeType.ConditionalExpression: { var cond_expr = (ConditionalExpression)node; if(!flow_manager.IsEvaluating(cond_expr)){ node = cond_expr.Condition; flow_manager.Push(cond_expr); }else{ flow_manager.Pop(); node = (bool)flow_manager.PopValue() ? cond_expr.TrueExpression : cond_expr.FalseExpression; } goto MAIN_LOOP; } case NodeType.Constant: flow_manager.PushValue(((LiteralExpression)node).Value); break; case NodeType.ContinueStatement: { var continue_stmt = (ContinueStatement)node; for(int i = continue_stmt.Count; i > 0;){ //Count階層分ループを遡るまで出会ったbreakableをノードスタックから取り除く AstNode popped = flow_manager.Pop().TargetNode; if(popped.Type == NodeType.ForStatement || popped.Type == NodeType.WhileStatement && i != 1) //continueすべきループはスタックから外さない --i; } break; } case NodeType.DefaultExpression: { var default_expr = (DefaultExpression)node; flow_manager.PushValue(ExpressoOps.GetDefaultValueFor(default_expr.TargetType.ObjType)); break; } case NodeType.ExprStatement: { var expr_stmt = (ExpressionStatement)node; if(!flow_manager.IsEvaluating(expr_stmt)) flow_manager.Push(expr_stmt); if(flow_manager.Top().ChildCounter < expr_stmt.Expressions.Length){ node = expr_stmt.Expressions[flow_manager.Top().ChildCounter++]; goto MAIN_LOOP; }else{ flow_manager.Pop(); } break; } case NodeType.FinallyClause: { var finally_clause = (FinallyClause)node; node = finally_clause.Body; goto case NodeType.Block; } case NodeType.ForStatement: { var for_stmt = (ForStatement)node; if(!flow_manager.IsEvaluating(for_stmt)) flow_manager.Push(for_stmt); switch(flow_manager.Top().StepCounter){ case 0: node = for_stmt.Target; flow_manager.Top().StepCounter++; goto MAIN_LOOP; case 1: { object iterable = flow_manager.TopValue(); if(!(iterable is IEnumerable)) throw ExpressoOps.MakeInvalidTypeError("Can not evaluate the expression to an iterable object!"); Identifier[] lvalues = new Identifier[for_stmt.Left.Count]; for(int i = 0; i < for_stmt.Left.Count; ++i){ lvalues[i] = for_stmt.Left.Items[i] as Identifier; if(lvalues[i] == null) throw ExpressoOps.MakeReferenceError("The left-hand-side of the \"in\" keyword must be a lvalue(a referencible value such as variables)"); } flow_manager.PushValue(lvalues); flow_manager.Top().StepCounter++; goto case 2; } case 2: Identifier[] lhs = (Identifier[])flow_manager.TopValue(); object iterable_obj = flow_manager.GetValue(flow_manager.ValueCount - 2); var rvalue = ExpressoOps.Enumerate(iterable_obj); if(rvalue.MoveNext()){ for(int j = 0; j < lhs.Length; ++j){ lhs[j].Assign(flow_manager.Top(), rvalue.Current); if(j + 1 != lhs.Length){ if(!rvalue.MoveNext()) throw ExpressoOps.MakeRuntimeError("The number of rvalues must be some multiple of that of lvalues."); } } node = for_stmt.Body; goto MAIN_LOOP; }else{ flow_manager.Pop(); } break; } break; } case NodeType.FunctionDef: //node = ((FunctionDefinition)node).Body; //goto MAIN_LOOP; flow_manager.PushValue(node); break; case NodeType.Identifier: { var ident = (Identifier)node; if(ident.Type.ObjType == ObjectTypes._Subscript){ flow_manager.PushValue(ident); }else if(ident.IsResolved){ flow_manager.Top().Dup(ident.Offset); }else if(ident.ParamType.ObjType == ObjectTypes.TypeClass){ var cur_module = flow_manager.Top().Get(0) as ExpressoObj; if(cur_module == null) throw ExpressoOps.MakeRuntimeError("\"this\" doesn't refer to the enclosing class instance."); flow_manager.PushValue(cur_module.AccessMember(ident, true)); }else if(ident.ParamType.ObjType == ObjectTypes.TypeModule){ var module = context.LanguageContext.GetModule(ident.Name); if(module == null) throw ExpressoOps.MakeRuntimeError(string.Format("The requested module \"{0}\" doesn't exist.", ident.Name)); flow_manager.PushValue(module); } break; } case NodeType.IfStatement: { var if_stmt = (IfStatement)node; if(!flow_manager.IsEvaluating(if_stmt)){ node = if_stmt.Condition; flow_manager.Push(if_stmt); }else{ flow_manager.Pop(); node = (bool)flow_manager.PopValue() ? if_stmt.TrueBlock : if_stmt.FalseBlock; } goto MAIN_LOOP; } case NodeType.Initializer: { var initializer = (SequenceInitializer)node; if(!flow_manager.IsEvaluating(initializer)) flow_manager.Push(initializer); if(flow_manager.Top().ChildCounter < initializer.Items.Length){ node = initializer.Items[flow_manager.Top().ChildCounter++]; goto MAIN_LOOP; }else{ flow_manager.Pop(); switch(initializer.ObjectType){ case ObjectTypes.List: { var values = new List<object>(initializer.Items.Length); for(int i = initializer.Items.Length; i > 0; --i) values.Add(flow_manager.PopValue()); values.Reverse(); //スタックからポップした順番では、逆順になってしまうので、順序を入れ替える flow_manager.PushValue(ExpressoOps.MakeList(values)); break; } case ObjectTypes.Tuple: { var values = new List<object>(initializer.Items.Length); for(int i = initializer.Items.Length; i > 0; --i) values.Add(flow_manager.PopValue()); values.Reverse(); //スタックからポップした順番では、逆順になってしまうので、順序を入れ替える flow_manager.PushValue(ExpressoOps.MakeTuple(values)); break; } case ObjectTypes.Dict: { var keys = new List<object>(initializer.Items.Length / 2); var values = new List<object>(initializer.Items.Length / 2); for(int i = initializer.Items.Length; i > 0; --i){ if(i % 2 == 1) keys.Add(flow_manager.PopValue()); else values.Add(flow_manager.PopValue()); } keys.Reverse(); //スタックからポップした順番では逆順になってしまうので、順序を入れ替える values.Reverse(); flow_manager.PushValue(ExpressoOps.MakeDict(keys, values)); break; } default: throw ExpressoOps.MakeRuntimeError("Unknown type of initializer!"); } } break; } case NodeType.MemRef: { var mem_ref = (MemberReference)node; if(!flow_manager.IsEvaluating(mem_ref)) flow_manager.Push(mem_ref); switch(flow_manager.Top().StepCounter){ case 0: node = mem_ref.Target; flow_manager.Top().StepCounter++; goto MAIN_LOOP; case 1: node = mem_ref.Subscription; flow_manager.Top().StepCounter++; goto MAIN_LOOP; case 2: flow_manager.Pop(); var subscription = flow_manager.PopValue(); var obj = flow_manager.PopValue(); if(subscription is ExpressoIntegerSequence){ var seq = (ExpressoIntegerSequence)subscription; flow_manager.PushValue(ExpressoOps.Slice(obj, seq)); }else if(obj is ExpressoObj){ var exs_obj = (ExpressoObj)obj; var member = exs_obj.AccessMember(subscription, obj == flow_manager.Top().Get(0)); flow_manager.PushValue(member); }else{ var member = ExpressoOps.AccessMember(obj, subscription); flow_manager.PushValue(member); } break; default: throw ExpressoOps.MakeSystemError("Unknown path reached while evaluating a member reference expression!"); } break; } case NodeType.Toplevel: { var toplevel = (ExpressoAst)node; if(!flow_manager.IsEvaluating(toplevel)) flow_manager.Push(toplevel); if(flow_manager.Top().ChildCounter < toplevel.Body.Length){ node = toplevel.Body[flow_manager.Top().ChildCounter++]; goto MAIN_LOOP; }else{ if(toplevel.IsModule){ var internals = new Dictionary<string, int>(); var exported = new Dictionary<string, int>(); Dictionary<string, int> decl_target = null; var members = new List<object>(); int offset = 0; for(int i = 0; i < toplevel.Body.Length; ++i){ decl_target = toplevel.ExportMap.Get(i) ? exported : internals; var stmt = toplevel.Body[i]; object val = flow_manager.Top().Get(offset); if(stmt is ExpressionStatement){ var expr_stmt = (ExpressionStatement)stmt; if(expr_stmt.Expressions[0] is VariableDeclarationStatement){ var var_decls = (VariableDeclarationStatement)expr_stmt.Expressions[0]; for(int j = 0; j < var_decls.Left.Length; ++j){ val = flow_manager.Top().Get(offset); decl_target.Add(var_decls.Left[j].Name, offset++); members.Add(val); //val = flow_manager.Top().Get(offset); //varStore.Add(var_decls.Variables[i].Offset, obj); //モジュールスコープの変数ストアにも実体を追加しておく } }else{ throw ExpressoOps.MakeInvalidTypeError("A module declaration can not have that type of statements!"); } }else if(stmt is FunctionDeclaration){ var method = (FunctionDeclaration)stmt; decl_target.Add(method.Name, offset++); members.Add(val); }else if(stmt is TypeDefinition){ var type_decl = (TypeDefinition)stmt; var type_def = flow_manager.Top().Get(offset); decl_target.Add(type_decl.Name, offset++); members.Add(type_def); }else{ throw ExpressoOps.MakeInvalidTypeError("A module declaration can not have that type of statements!"); } } var module_def = new ModuleDefinition(toplevel.ModuleName, internals, exported, members.ToArray()); var module_inst = new ExpressoModule(module_def); context.LanguageContext.PublishModule(toplevel.ModuleName, module_inst); } flow_manager.Pop(); } break; } case NodeType.New: { var new_expr = (NewExpression)node; if(!flow_manager.IsEvaluating(new_expr)){ node = new_expr.CreationExpression; flow_manager.Push(new_expr); goto MAIN_LOOP; }else{ flow_manager.Pop(); var type_def = flow_manager.PopValue() as BaseDefinition; if(type_def == null) throw ExpressoOps.MakeInvalidTypeError("{0} doesn't refer to a type name.", new_expr.CreationExpression); flow_manager.PushValue(ExpressoObj.CreateInstance(null, type_def, new_expr.Arguments)); } break; } case NodeType.Print: { var print_stmt = (PrintStatement)node; if(!flow_manager.IsEvaluating(print_stmt)) flow_manager.Push(print_stmt); if(flow_manager.Top().ChildCounter < print_stmt.Expressions.Length){ node = print_stmt.Expressions[flow_manager.Top().ChildCounter++]; goto MAIN_LOOP; }else{ flow_manager.Pop(); var values = new List<object>(print_stmt.Expressions.Length); for(int i = print_stmt.Expressions.Length; i > 0; --i) values.Add(flow_manager.PopValue()); ExpressoOps.DoPrint(values, print_stmt.HasTrailing); } break; } case NodeType.Require: { var require_expr = (ImportDeclaration)node; foreach(var module_name in require_expr.ModuleNames){ var path = module_name.Replace('.', '/'); path += ".exs"; path = GetRelativePathToCurrentSource(path); var module_parser = new Parser(new Scanner(path)); module_parser.ParsingFileName = module_name; module_parser.Parse(); Interpret(module_parser.TopmostAst, context); } break; } case NodeType.Return: { var return_stmt = (ReturnStatement)node; if(return_stmt.Expression != null){ if(!flow_manager.IsEvaluating(return_stmt)){ flow_manager.Push(return_stmt); node = return_stmt.Expression; goto MAIN_LOOP; }else{ flow_manager.Pop(); ExpressoTuple ret = (ExpressoTuple)flow_manager.PopValue(); if(ret.Count == 1) flow_manager.PushValue(ret[0]); else flow_manager.PushValue(ret); } } break; } case NodeType.IntSequence: { var intseq_expr = (IntegerSequenceExpression)node; if(!flow_manager.IsEvaluating(intseq_expr)) flow_manager.Push(intseq_expr); switch(flow_manager.Top().StepCounter){ case 0: node = intseq_expr.Lower; flow_manager.Top().StepCounter++; goto MAIN_LOOP; case 1: node = intseq_expr.Upper; flow_manager.Top().StepCounter++; goto MAIN_LOOP; case 2: node = intseq_expr.Step; flow_manager.Top().StepCounter++; goto MAIN_LOOP; case 3: flow_manager.Pop(); var step = flow_manager.PopValue(); var end = flow_manager.PopValue(); var start = flow_manager.PopValue(); if(!(start is int) || !(end is int) || !(step is int)) throw ExpressoOps.MakeInvalidTypeError("The start, end and step expressions of the IntSeq expression must yield an integer."); flow_manager.PushValue(new ExpressoIntegerSequence((int)start, (int)end, (int)step)); break; default: throw ExpressoOps.MakeSystemError("An error occurred while evaluating an IntegerSequence expression."); } break; } case NodeType.Sequence: { var seq_expr = (SequenceExpression)node; if(!flow_manager.IsEvaluating(seq_expr)) flow_manager.Push(seq_expr); if(flow_manager.Top().ChildCounter < seq_expr.Count){ node = seq_expr.Items[flow_manager.Top().ChildCounter++]; goto MAIN_LOOP; }else{ flow_manager.Pop(); var item_values = new object[seq_expr.Count]; for(int i = seq_expr.Count - 1; i >= 0; --i) item_values[i] = flow_manager.PopValue(); flow_manager.PushValue(ExpressoOps.MakeTuple(item_values)); } break; } case NodeType.SwitchStatement: { var switch_stmt = (MatchStatement)node; if(!flow_manager.IsEvaluating(switch_stmt)) flow_manager.Push(switch_stmt); switch(flow_manager.Top().StepCounter){ case 0: node = switch_stmt.Target; flow_manager.Top().StepCounter++; goto MAIN_LOOP; case 1: if(flow_manager.Top().ChildCounter < switch_stmt.Clauses.Length){ if(flow_manager.Top().ChildCounter != 0){ object top = flow_manager.PopValue(); if(top is bool && (bool)top) goto CLEANUP_SWITCH; } node = switch_stmt.Clauses[flow_manager.Top().ChildCounter++]; goto MAIN_LOOP; }else{ flow_manager.Pop(); } CLEANUP_SWITCH: flow_manager.PopValue(); //caseラベルと照合する値をスタックから外す break; default: throw ExpressoOps.MakeSystemError("Unknown path reached while evaluating a switch statement!"); } break; } case NodeType.ThrowStatement: { var throw_stmt = (ThrowStatement)node; if(!flow_manager.IsEvaluating(throw_stmt)){ node = throw_stmt.Expression; flow_manager.Push(throw_stmt); goto MAIN_LOOP; }else{ flow_manager.Pop(); } break; } case NodeType.TryStatement: { var try_stmt = (TryStatement)node; if(!flow_manager.IsEvaluating(try_stmt)){ node = try_stmt.Body; flow_manager.Push(try_stmt); goto case NodeType.Block; }else{ //ノードスタックのトップがこのtry文だった場合、try文の本体の実行は終わっている var top = flow_manager.TopValue(); if(top is ExpressoThrowException){ if(try_stmt.Catches != null){ node = try_stmt.Catches[flow_manager.Top().ChildCounter++]; goto case NodeType.CatchClause; }else{ flow_manager.Pop(); while(flow_manager.Count > 0){ //一つ上のtry文にたどり着くまでノードスタックを巻き戻す flow_manager.Pop(); if(flow_manager.Top().TargetNode.Type == NodeType.TryStatement) break; //NOTE: 次のループに入る前に親のノードを参照するので、ここでは何もしない } if(flow_manager.Count == 0) //このtry文を内包するtry文が見つからなかったので、C#側の例外ハンドラに処理を投げる throw (ExpressoThrowException)top; } } if(try_stmt.FinallyClause != null){ node = try_stmt.FinallyClause; if(flow_manager.IsEvaluating(try_stmt)) //finally節を実行したらこのtry文には用はなくなる flow_manager.Pop(); goto case NodeType.FinallyClause; } flow_manager.Pop(); //ここに到達するのはfinally節がなく、try文の本体で例外が発生しなかった場合だけ } break; } case NodeType.TypeDef: { var type_def = (TypeDefinition)node; if(!flow_manager.IsEvaluating(type_def)) flow_manager.Push(type_def); switch(flow_manager.Top().StepCounter){ case 0: if(flow_manager.Top().ChildCounter < type_def.Bases.Length){ node = type_def.Bases[flow_manager.Top().ChildCounter++]; goto MAIN_LOOP; }else{ flow_manager.Top().ChildCounter = 0; flow_manager.Top().StepCounter++; goto case 1; } case 1: if(flow_manager.Top().ChildCounter < type_def.Body.Length){ node = type_def.Body[flow_manager.Top().ChildCounter++]; goto MAIN_LOOP; }else{ flow_manager.Top().StepCounter++; goto case 2; } case 2: var private_members = new Dictionary<string, int>(); var public_members = new Dictionary<string, int>(); var members = new List<object>(); int offset = 0; for(int i = 0; i < type_def.Body.Length; ++i){ var stmt = type_def.Body[i]; object val = flow_manager.Top().Get(offset); if(stmt is ExpressionStatement){ var expr_stmt = (ExpressionStatement)stmt; if(expr_stmt.Expressions[0] is VariableDeclarationStatement){ var var_decls = (VariableDeclarationStatement)expr_stmt.Expressions[0]; for(int j = 0; j < var_decls.Left.Length; ++j){ val = flow_manager.Top().Get(offset); if(var_decls.HasFlag(Flags.PrivateAccess)) private_members.Add(var_decls.Left[j].Name, offset++); else if(var_decls.HasFlag(Flags.PublicAccess)) public_members.Add(var_decls.Left[j].Name, offset++); members.Add(val); } }else{ throw ExpressoOps.MakeInvalidTypeError("A type declaration can not have that type of statements!"); } }else if(stmt is FunctionDeclaration){ var method = (FunctionDeclaration)stmt; if(method.HasFlag(Flags.PrivateAccess)) private_members.Add(method.Name, offset++); else if(method.HasFlag(Flags.PublicAccess)) public_members.Add(method.Name, offset++); members.Add(val); }else{ throw ExpressoOps.MakeInvalidTypeError("A type declaration can not have that type of statements!"); } } //継承元の型定義をスタックから参照する var base_definitions = new List<BaseDefinition>(); for(int i = 0; i < type_def.Bases.Length; ++i){ BaseDefinition base_def = flow_manager.Top().Get(i) as BaseDefinition; if(base_def == null){ throw ExpressoOps.MakeRuntimeError("Something wrong has occurred.\n Could not find base type '{0}'", type_def.Bases[i].Name); } base_definitions.Add(base_def); } object def_object = null; switch(type_def.TargetType){ case DeclType.Interface: def_object = new InterfaceDefinition(type_def.Name, public_members, members.ToArray(), base_definitions); break; case DeclType.Class: def_object = new ClassDefinition(type_def.Name, private_members, public_members, members.ToArray(), base_definitions); break; case DeclType.Struct: def_object = new StructDefinition(type_def.Name, private_members, public_members, members.ToArray(), base_definitions); break; } flow_manager.PushValue(def_object); flow_manager.Pop(); break; default: throw ExpressoOps.MakeSystemError("Unknown path reached while evaluating a type definition."); } break; } case NodeType.UnaryExpression: { var unary_op = (UnaryExpression)node; if(!flow_manager.IsEvaluating(unary_op)){ node = unary_op.Operand; flow_manager.Push(unary_op); goto MAIN_LOOP; }else{ flow_manager.Pop(); var ope = flow_manager.PopValue(); if(ope == null) throw ExpressoOps.MakeInvalidTypeError("Invalid object type!"); flow_manager.PushValue(EvalUnaryOperation(unary_op.Operator, ope)); } break; } case NodeType.VarDecl: { var var_decl = (VariableDeclarationStatement)node; if(!flow_manager.IsEvaluating(var_decl)) flow_manager.Push(var_decl); int child_counter = flow_manager.Top().ChildCounter; if(child_counter < var_decl.Left.Length){ node = var_decl.Expressions[flow_manager.Top().ChildCounter++]; goto MAIN_LOOP; }else{ flow_manager.Pop(); } break; } case NodeType.WhileStatement: { var while_stmt = (WhileStatement)node; if(!flow_manager.IsEvaluating(while_stmt)) flow_manager.Push(while_stmt); switch(flow_manager.Top().StepCounter){ case 0: node = while_stmt.Condition; flow_manager.Top().StepCounter++; goto MAIN_LOOP; case 1: var cond = flow_manager.PopValue(); try{ if(cond != null && (bool)cond){ node = while_stmt.Body; flow_manager.Top().StepCounter--; goto MAIN_LOOP; }else{ flow_manager.Pop(); } } catch(Exception){ if(!(cond is bool)) throw ExpressoOps.MakeInvalidTypeError("Invalid expression! The condition of a while statement must yield a boolean!"); } break; default: throw ExpressoOps.MakeSystemError("Unknown path reached while evaluating a while statement!"); } break; } case NodeType.WithStatement: break; case NodeType.YieldStatement: break; default: throw ExpressoOps.MakeRuntimeError("Unknown AST type!"); } if(flow_manager.Count != 0) node = flow_manager.Top().TargetNode; else break; //評価スタックがなくなったので、ループを抜ける } } catch(Exception ex){ Type exception_type = ex.GetType(); Console.WriteLine("{0}: {1}", exception_type.FullName, ex.Message); Console.WriteLine("Stack trace: {0}", ex.StackTrace); } Debug.Assert(flow_manager.ValueCount == 0 || flow_manager.ValueCount == 1); return (flow_manager.ValueCount > 0) ? flow_manager.PopValue() : null; }