/// <summary> /// 式からなる<see cref="KecaknoahAst"/>をプリコンパイルします。 /// </summary> /// <param name="ast">対象の<see cref="KecaknoahAst"/></param> /// <returns>プリコンパイル結果</returns> public KecaknoahIL PrecompileExpression(KecaknoahAst ast) { var result = new KecaknoahIL(); result.PushCodes(PrecompileExpression(ast.RootNode)); return(result); }
private KecaknoahScriptClassInfo PrecompileClass(KecaknoahClassAstNode ast) { //TODO: local初期値式対応 var result = new KecaknoahScriptClassInfo(ast.Name); cuc.Push(result); foreach (var i in ast.Functions) { if (i.StaticMethod) { result.AddClassMethod(PrecompileFunction(i)); } else { result.AddInstanceMethod(PrecompileFunction(i)); } } foreach (var i in ast.Locals) { if (i.InitialExpression != null) { var il = new KecaknoahIL(); il.PushCodes(PrecompileExpression(i.InitialExpression)); result.AddLocal(i.Name, il); } else { result.AddLocal(i.Name, null); } } cuc.Pop(); return result; }
internal IReadOnlyList <KecaknoahILCode> PrecompileBlock(IReadOnlyList <KecaknoahAstNode> ast, string loopId) { var result = new KecaknoahIL(); List <string> locals = new List <string>(); foreach (var i in ast) { if (i is KecaknoahExpressionAstNode) { if (i is KecaknoahFactorExpressionAstNode) { var exp = i as KecaknoahFactorExpressionAstNode; if (exp.FactorType != KecaknoahFactorType.CoroutineResume) { throw new InvalidOperationException("ステートメントにできる式はcoresume・代入・呼び出し・インクリメント・デクリメントのみです"); } } else if (i is KecaknoahArgumentCallExpressionAstNode) { var exp = i as KecaknoahArgumentCallExpressionAstNode; if (exp.ExpressionType != KecaknoahOperatorType.FunctionCall) { throw new InvalidOperationException("ステートメントにできる式はcoresume・代入・呼び出し・インクリメント・デクリメントのみです"); } result.PushCodes(PrecompileFunctionCall(exp)); result.PushCode(KecaknoahILCodeType.Pop); } else if (i is KecaknoahBinaryExpressionAstNode) { var exp = i as KecaknoahBinaryExpressionAstNode; switch (exp.ExpressionType) { case KecaknoahOperatorType.Assign: case KecaknoahOperatorType.PlusAssign: case KecaknoahOperatorType.MinusAssign: case KecaknoahOperatorType.MultiplyAssign: case KecaknoahOperatorType.DivideAssign: case KecaknoahOperatorType.AndAssign: case KecaknoahOperatorType.OrAssign: case KecaknoahOperatorType.XorAssign: case KecaknoahOperatorType.ModularAssign: case KecaknoahOperatorType.LeftBitShiftAssign: case KecaknoahOperatorType.RightBitShiftAssign: case KecaknoahOperatorType.NilAssign: result.PushCodes(PrecompileBinaryExpression(exp)); result.PushCode(KecaknoahILCodeType.Pop); break; default: throw new InvalidOperationException("ステートメントにできる式はcoresume・代入・呼び出し・インクリメント・デクリメントのみです"); } } else if (i is KecaknoahPrimaryExpressionAstNode) { var exp = i as KecaknoahPrimaryExpressionAstNode; switch (exp.ExpressionType) { case KecaknoahOperatorType.Increment: result.PushCodes(PrecompileSuffixIncrement(exp)); result.PushCode(KecaknoahILCodeType.Pop); break; case KecaknoahOperatorType.Decrement: result.PushCodes(PrecompileSuffixDecrement(exp)); result.PushCode(KecaknoahILCodeType.Pop); break; default: throw new InvalidOperationException("ステートメントにできる式はcoresume・代入・呼び出し・インクリメント・デクリメントのみです"); } } else if (i is KecaknoahUnaryExpressionAstNode) { var exp = i as KecaknoahUnaryExpressionAstNode; switch (exp.ExpressionType) { case KecaknoahOperatorType.Increment: result.PushCodes(PrecompilePrefixIncrement(exp)); result.PushCode(KecaknoahILCodeType.Pop); break; case KecaknoahOperatorType.Decrement: result.PushCodes(PrecompilePrefixDecrement(exp)); result.PushCode(KecaknoahILCodeType.Pop); break; default: throw new InvalidOperationException("ステートメントにできる式はcoresume・代入・呼び出し・インクリメント・デクリメントのみです"); } } else { throw new InvalidOperationException("ステートメントにできる式はcoresume・代入・呼び出し・インクリメント・デクリメントのみです"); } } else if (i is KecaknoahLocalAstNode) { var lc = i as KecaknoahLocalAstNode; locals.Add(lc.Name); if (lc.InitialExpression != null) { result.PushCode(KecaknoahILCodeType.LoadObject, lc.Name); result.PushCodes(PrecompileExpression(lc.InitialExpression)); result.PushCode(KecaknoahILCodeType.Assign); } } else if (i is KecaknoahReturnAstNode) { var rc = i as KecaknoahReturnAstNode; if (rc.Value != null) { result.PushCodes(PrecompileExpression(rc.Value)); } else { result.PushCode(KecaknoahILCodeType.PushNil); } result.PushCode(rc.Type == KecaknoahAstNodeType.ReturnStatement ? KecaknoahILCodeType.Return : KecaknoahILCodeType.Yield); } else if (i is KecaknoahCoroutineDeclareAstNode) { var cd = i as KecaknoahCoroutineDeclareAstNode; result.PushCodes(PrecompileExpression(cd.InitialExpression)); foreach (var pe in cd.ParameterExpressions) { result.PushCodes(PrecompileExpression(pe)); } result.PushCode(new KecaknoahILCode { Type = KecaknoahILCodeType.StartCoroutine, StringValue = cd.Name, IntegerValue = cd.ParameterExpressions.Count }); } else if (i is KecaknoahContinueAstNode) { var ca = i as KecaknoahContinueAstNode; var ln = ca.Label != "" ? ca.Label : loopId; result.PushCode(KecaknoahILCodeType.Jump, $"{ln}-" + (i.Type == KecaknoahAstNodeType.ContinueStatement ? "Continue" : "End")); } else if (i is KecaknoahIfAstNode) { result.PushCodes(PrecompileIf(i as KecaknoahIfAstNode, loopId)); } else if (i is KecaknoahForAstNode) { result.PushCodes(PrecompileFor(i as KecaknoahForAstNode)); } else if (i is KecaknoahForeachAstNode) { result.PushCodes(PrecompileForeach(i as KecaknoahForeachAstNode)); } else if (i is KecaknoahLoopAstNode) { result.PushCodes(PrecompileWhile(i as KecaknoahLoopAstNode)); } } return(result.Codes); }
internal IReadOnlyList<KecaknoahILCode> PrecompileBlock(IReadOnlyList<KecaknoahAstNode> ast, string loopId) { var result = new KecaknoahIL(); List<string> locals = new List<string>(); foreach (var i in ast) { if (i is KecaknoahExpressionAstNode) { if (i is KecaknoahFactorExpressionAstNode) { var exp = i as KecaknoahFactorExpressionAstNode; if (exp.FactorType != KecaknoahFactorType.CoroutineResume) throw new InvalidOperationException("ステートメントにできる式はcoresume・代入・呼び出し・インクリメント・デクリメントのみです"); } else if (i is KecaknoahArgumentCallExpressionAstNode) { var exp = i as KecaknoahArgumentCallExpressionAstNode; if (exp.ExpressionType != KecaknoahOperatorType.FunctionCall) throw new InvalidOperationException("ステートメントにできる式はcoresume・代入・呼び出し・インクリメント・デクリメントのみです"); result.PushCodes(PrecompileFunctionCall(exp)); result.PushCode(KecaknoahILCodeType.Pop); } else if (i is KecaknoahBinaryExpressionAstNode) { var exp = i as KecaknoahBinaryExpressionAstNode; switch (exp.ExpressionType) { case KecaknoahOperatorType.Assign: case KecaknoahOperatorType.PlusAssign: case KecaknoahOperatorType.MinusAssign: case KecaknoahOperatorType.MultiplyAssign: case KecaknoahOperatorType.DivideAssign: case KecaknoahOperatorType.AndAssign: case KecaknoahOperatorType.OrAssign: case KecaknoahOperatorType.XorAssign: case KecaknoahOperatorType.ModularAssign: case KecaknoahOperatorType.LeftBitShiftAssign: case KecaknoahOperatorType.RightBitShiftAssign: case KecaknoahOperatorType.NilAssign: result.PushCodes(PrecompileBinaryExpression(exp)); result.PushCode(KecaknoahILCodeType.Pop); break; default: throw new InvalidOperationException("ステートメントにできる式はcoresume・代入・呼び出し・インクリメント・デクリメントのみです"); } } else if (i is KecaknoahPrimaryExpressionAstNode) { var exp = i as KecaknoahPrimaryExpressionAstNode; switch (exp.ExpressionType) { case KecaknoahOperatorType.Increment: result.PushCodes(PrecompileSuffixIncrement(exp)); result.PushCode(KecaknoahILCodeType.Pop); break; case KecaknoahOperatorType.Decrement: result.PushCodes(PrecompileSuffixDecrement(exp)); result.PushCode(KecaknoahILCodeType.Pop); break; default: throw new InvalidOperationException("ステートメントにできる式はcoresume・代入・呼び出し・インクリメント・デクリメントのみです"); } } else if (i is KecaknoahUnaryExpressionAstNode) { var exp = i as KecaknoahUnaryExpressionAstNode; switch (exp.ExpressionType) { case KecaknoahOperatorType.Increment: result.PushCodes(PrecompilePrefixIncrement(exp)); result.PushCode(KecaknoahILCodeType.Pop); break; case KecaknoahOperatorType.Decrement: result.PushCodes(PrecompilePrefixDecrement(exp)); result.PushCode(KecaknoahILCodeType.Pop); break; default: throw new InvalidOperationException("ステートメントにできる式はcoresume・代入・呼び出し・インクリメント・デクリメントのみです"); } } else { throw new InvalidOperationException("ステートメントにできる式はcoresume・代入・呼び出し・インクリメント・デクリメントのみです"); } } else if (i is KecaknoahLocalAstNode) { var lc = i as KecaknoahLocalAstNode; locals.Add(lc.Name); if (lc.InitialExpression != null) { result.PushCode(KecaknoahILCodeType.LoadObject, lc.Name); result.PushCodes(PrecompileExpression(lc.InitialExpression)); result.PushCode(KecaknoahILCodeType.Assign); } } else if (i is KecaknoahReturnAstNode) { var rc = i as KecaknoahReturnAstNode; if (rc.Value != null) { result.PushCodes(PrecompileExpression(rc.Value)); } else { result.PushCode(KecaknoahILCodeType.PushNil); } result.PushCode(rc.Type == KecaknoahAstNodeType.ReturnStatement ? KecaknoahILCodeType.Return : KecaknoahILCodeType.Yield); } else if (i is KecaknoahCoroutineDeclareAstNode) { var cd = i as KecaknoahCoroutineDeclareAstNode; result.PushCodes(PrecompileExpression(cd.InitialExpression)); foreach (var pe in cd.ParameterExpressions) result.PushCodes(PrecompileExpression(pe)); result.PushCode(new KecaknoahILCode { Type = KecaknoahILCodeType.StartCoroutine, StringValue = cd.Name, IntegerValue = cd.ParameterExpressions.Count }); } else if (i is KecaknoahContinueAstNode) { var ca = i as KecaknoahContinueAstNode; result.PushCode(KecaknoahILCodeType.Jump, $"{loopId}-" + (i.Type == KecaknoahAstNodeType.ContinueStatement ? "Continue" : "End")); } else if (i is KecaknoahIfAstNode) { result.PushCodes(PrecompileIf(i as KecaknoahIfAstNode, loopId)); } else if (i is KecaknoahForAstNode) { result.PushCodes(PrecompileFor(i as KecaknoahForAstNode)); } else if (i is KecaknoahForeachAstNode) { result.PushCodes(PrecompileForeach(i as KecaknoahForeachAstNode)); } else if (i is KecaknoahLoopAstNode) { result.PushCodes(PrecompileWhile(i as KecaknoahLoopAstNode)); } } return result.Codes; }
/// <summary> /// 式からなる<see cref="KecaknoahAst"/>をプリコンパイルします。 /// </summary> /// <param name="ast">対象の<see cref="KecaknoahAst"/></param> /// <returns>プリコンパイル結果</returns> public KecaknoahIL PrecompileExpression(KecaknoahAst ast) { var result = new KecaknoahIL(); result.PushCodes(PrecompileExpression(ast.RootNode)); return result; }
private IList<KecaknoahILCode> PrecompileClassLambda(IList<KecaknoahILCode> il, List<string> lma) { var caps = new List<string>(); for (int i = 0; i < il.Count; i++) { var c = il[i]; if (c.Type == KecaknoahILCodeType.LoadObject) { var name = c.StringValue; if (lma.Contains(name)) { c.Type = KecaknoahILCodeType.PushArgument; c.IntegerValue = lma.IndexOf(name); } } } var ln = $"Lambda-{Guid.NewGuid().ToString().Substring(0, 17)}"; ; var mi = new KecaknoahScriptMethodInfo(ln, lma.Count, false); var lc = new KecaknoahIL(); lc.PushCodes(il); mi.Codes = lc; var result = new List<KecaknoahILCode>(); current.methods.Add(mi); result.Add(new KecaknoahILCode { Type = KecaknoahILCodeType.LoadObject, StringValue = ln }); return result; }