public EvaluationFrame(AstNode node, int framePointer, int childCounter, InterpreterFlowManager flowManager) { TargetNode = node; ScopeFramePointer = framePointer; ChildCounter = childCounter; StepCounter = 0; manager = flowManager; }
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; }