public static object Return(VarCtx varCtx, object value) { varCtx.Func.ReturnValue = value; varCtx.Func.Returned = true; varCtx.Break = VarCtx.BreakMode.Return; return(value); }
VarCtx EnterInterpreter(FuncCtx entry, object[] args) { var resultHolder = new VarCtx(null, null, null, this); try { Result = Block.CallFunc(resultHolder, entry, args); } catch (Exception e) { resultHolder.Break = VarCtx.BreakMode.Throw; resultHolder.ScriptException = new RuntimeException(e.Message, resultHolder); } if (resultHolder.Break == VarCtx.BreakMode.Throw) { if (OnException == null) { SyncDebug("Unhandleded exception: " + resultHolder.ScriptException); } else { SyncCtx.Send((d) => OnException(-1, resultHolder.ScriptException), null); } } return(resultHolder); }
private object UnaryArifm(VarCtx ctx, object a) { Type maxType = null; Type aType = a == null ? typeof(DumbNullType) : a.GetType(); foreach (var kp in Ops) { if (kp.Key.IsAssignableFrom(aType)) { maxType = kp.Key; break; } } ; if (maxType == null) { throw new Exception("Can't cast type for " + aType); } if (maxType.IsInterface) { return(Ops[maxType](a, null)); } //var ao = a == null ? null : Convert.ChangeType(a, maxType); return(Ops[maxType](a, null)); }
public static object DeclareFunc(VarCtx curCtx, Function func) { var funcCtx = new FuncCtx { ParentScope = curCtx, FunctionProto = func }; return(funcCtx); }
FuncCtx CreateFunc(VarCtx scope, string name, Func <VarCtx, object[], object> func) { return(CreateFunc(scope, name, new Function { ArgNames = new string[] { }, Native = func })); }
public VarCtx(VarCtx parentOnStack, VarCtx parScope, Block block, Interpreter interp) { CurBlock = block; ParentOnStack = parentOnStack; ParentScope = parScope; Func = parScope?.Func; Interp = interp; }
FuncCtx CreateSynchronizedFunc(VarCtx scope, string name, Func <VarCtx, object[], object> func) { return(CreateFunc(scope, name, (c, d) => { object result = null; SyncCtx.Send((state) => result = func(c, d), null); return result; }));; }
public static object NewList(VarCtx curCtx, object length) { var len = GetArrayKey(length); if (len >= 0) { return(new object[len].ToList()); } return(Throw(curCtx, "Invalid array length " + length)); }
FuncCtx CreateFunc(VarCtx scope, string name, Function func) { func.Name = name; var result = new FuncCtx { FunctionProto = func, ParentScope = scope }; return(result); }
public object Arifm(VarCtx ctx, object a, object b) { try { if (Unary) { return(UnaryArifm(ctx, a)); } Type aType = a == null ? typeof(DumbNullType) : a.GetType(); Type bType = b == null ? typeof(DumbNullType) : b.GetType(); Type maxType = null; foreach (var kp in Ops) { //ctx.Interp.SyncDebug($"{aType} + {bType} ? {kp.Key}"); if (kp.Key.IsAssignableFrom(aType) || kp.Key.IsAssignableFrom(bType)) { maxType = kp.Key; break; } } ; if (maxType == null) { throw new Exception("Can't cast types"); } if (maxType.IsInterface) { return(Ops[maxType](a, b)); } if (maxType.IsPrimitive) { a = Convert.ChangeType(a, maxType); b = Convert.ChangeType(b, maxType); } else if (maxType == typeof(string)) { a = a.ToString(); b = b.ToString(); } //var ao = a == null ? null : (maxType == typeof(object) ? a : Convert.ChangeType(a, maxType)); //var bo = b == null ? null : (maxType == typeof(object) ? b : Convert.ChangeType(b, maxType)); var result = Ops[maxType](a, b); //ctx.Interp.SyncDebug($"{a}({aType}) {this} {b}({bType}) -> {result}"); return(result); } catch (Exception e) { return(Block.Throw(ctx, e.Message)); } }
public static object CallFunc(VarCtx ctx, object f, object[] args) { if (ctx.Break == VarCtx.BreakMode.Throw) { return(null); } if (!(f is FuncCtx func)) { return(Throw(ctx, $"{f} is not a function")); } if (new RuntimeException(null, ctx).StackTrace().Count() > 200) { return(Throw(ctx, $"Stack overflow exception while calling {f}")); } var funcVarCtx = new VarCtx(ctx, func.ParentScope, func.FunctionProto.Body); funcVarCtx.Func = func; if (func.FunctionProto.Body != null) { funcVarCtx.Vars["arguments"] = args ?? new object[0]; for (int i = 0; i < func.FunctionProto.ArgNames.Length; ++i) { if (args != null && i < args.Length) { funcVarCtx.Vars[func.FunctionProto.ArgNames[i]] = args[i]; } else { funcVarCtx.Vars[func.FunctionProto.ArgNames[i]] = null; } } return(func.FunctionProto.Body.RunBlock(funcVarCtx)); } else { // Native try { funcVarCtx.CurBlock = new Block() { Type = BlockType.Func }; return(func.FunctionProto.Native(funcVarCtx, args)); } catch (Exception e) { return(Throw(funcVarCtx, e.ToString())); } } }
public static object SetVal(VarCtx varCtx, string key, object value) { var callCtx = varCtx; while (varCtx != null) { if (varCtx.Vars.ContainsKey(key)) { return(varCtx.Vars[key] = value); } varCtx = varCtx.ParentScope; } return(Throw(callCtx, $"{key}: undeclared variable")); }
public static object Throw(VarCtx varCtx, object v) { var exc = new RuntimeException(v, varCtx); while (varCtx != null) { varCtx.Break = VarCtx.BreakMode.Throw; varCtx.ScriptException = exc; if (varCtx.CurBlock != null && varCtx.CurBlock.Type == BlockType.Try) { break; } varCtx = varCtx.ParentOnStack; } return(Undefined); }
public override object RunBlock(VarCtx ctx) { ctx.Break = VarCtx.BreakMode.None; ctx.ScriptException = null; var result = RunExpr(ctx, Try); //ctx.Interp.SyncDebug(ctx.Break); if (ctx.Break != VarCtx.BreakMode.Throw) { return(result); } DeclareVar(ctx, ExceptionName, ctx.ScriptException); ctx.Break = VarCtx.BreakMode.None; return(RunExpr(ctx, Catch)); }
public object Apply(VarCtx varCtx, object dict, object key, object value) { var a = GetDictVal(varCtx, dict, key); if (varCtx.Break != VarCtx.BreakMode.None) { return(Undefined); } var r = op.Arifm(varCtx, a, value); SetDictVal(varCtx, dict, key, r); if (retOriginal) { return(a); } return(r); }
public static object Break(VarCtx varCtx, VarCtx.BreakMode mode) { while (varCtx != null) { varCtx.Break = mode; if (varCtx.CurBlock?.Type == BlockType.Loop) { break; } else if (varCtx.CurBlock == null || varCtx.CurBlock.Type != BlockType.Plain) { throw new Exception("Break too far"); // should never happen, checks on compilation } varCtx = varCtx.ParentOnStack; } return(null); }
public override object RunBlock(VarCtx ctx) { ctx.Break = VarCtx.BreakMode.None; object returnValue = null; if (Init != null) { RunExpr(ctx, Init); } if (ctx.Break == VarCtx.BreakMode.Throw) { return(null); } while ((Cond != null) ? CheckCond(ctx, RunExpr(ctx, Cond)) : true) { if (ctx.Break == VarCtx.BreakMode.Throw) { return(null); } var childCtx = new VarCtx(ctx, ctx, this); returnValue = base.RunBlock(childCtx); //ctx.Interp.SyncCtx.Send((s) => Debug.Log(childCtx.Break), null); if (childCtx.Break == VarCtx.BreakMode.Break || childCtx.Break == VarCtx.BreakMode.Return) { break; } if (ctx.Break == VarCtx.BreakMode.Throw) { return(null); } // "continue" does not need special handling if (Inc != null) { RunExpr(ctx, Inc); if (ctx.Break == VarCtx.BreakMode.Throw) { return(null); } } } return(returnValue); }
public virtual object RunBlock(VarCtx ctx) { ctx.Break = VarCtx.BreakMode.None; object returnValue = null; foreach (var expr in Exprs) { returnValue = RunExpr(ctx, expr); if (ctx.Break != VarCtx.BreakMode.None) { break; } } if (ctx.CurBlock?.Type == BlockType.Func) { return(ctx.Func.ReturnValue); } return(returnValue); }
public object Apply(VarCtx varCtx, object value) { var a = GetVal(varCtx, key); if (varCtx.Break != VarCtx.BreakMode.None) { return(Undefined); } var r = op.Arifm(varCtx, a, value); SetVal(varCtx, key, r); //varCtx.Interp.PauseThread((d) => Debug.Log($"Setvalarifm {key} {a} -> {r} {retOriginal}"), null); if (retOriginal) { return(a); } return(r); }
protected object RunExpr(VarCtx ctx, BuiltExpression e) { if (!CompiledCode.ContainsKey(e)) { CompiledCode[e] = Expression.Lambda(e.Expr, RuntimeVarCtx).Compile(); } ctx.Interp.IrqPoll(); ctx.Interp.Gas -= 1; ctx.PC = e; try { return(CompiledCode[e].DynamicInvoke(ctx)); } catch (Exception ee) { //ctx.Interp.SyncDebug(ee); Throw(ctx, new RuntimeException(ee.Message, ctx)); return(Undefined); } }
public FuncCtx PrepareScript(string script) { var lexer = new Lexer(script); var parser = new Parser(lexer); var root = parser.Parse(); //Debug.Log(root.Print("")); var rb = new Block(); rb.EAdd(Compile(rb, root)); rb.Type = Block.BlockType.Func; var rc = new VarCtx(null, null, null, this); var main = CreateFunc(rc, "main", new Function { Body = rb }); rc.AddVar("main", main); return(main); }
public static bool CheckCond(VarCtx curCtx, object v) { //curCtx.Interp.SyncDebug($"check {v}({v?.GetType()})"); if (v is bool b) { return(b); } if (v is long i) { return(i != 0); } if (v is float f) { return(f != 0); } if (v == Undefined) { return(false); } return(v != null); }
public static object GetDictVal(VarCtx ctx, object dict, object key) { if (dict is Dictionary <string, object> d) { var dkey = GetDictKey(key); if (!d.ContainsKey(dkey)) { return(Undefined); } return(d[dkey]); } else if (dict is List <object> arr) { if (key is string sk) { if (sk == "length") { return((long)arr.Count); } if (ctx.Interp.ArrayProto.ContainsKey(sk)) { return(DeclareFunc(ctx, ctx.Interp.ArrayProto[sk](arr))); } } var akey = GetArrayKey(key); if (akey >= 0) { if (akey < arr.Count) { return(arr[akey]); } return(Undefined); } } return(Throw(ctx, $"Can't read {dict}[{key}]")); }
public static object SetDictVal(VarCtx ctx, object dict, object key, object value) { if (dict is Dictionary <string, object> d) { var dkey = GetDictKey(key); if (dkey != null) { return(d[dkey] = value); } } else if (dict is List <object> arr) { var akey = GetArrayKey(key); if (akey >= 0) { if (akey < arr.Count) { return(arr[akey] = value); } return(Undefined); } } return(Throw(ctx, $"Can't write to {dict}[{key}]")); }
public VarCtx(VarCtx parentOnStack, VarCtx parScope, Block block) : this(parentOnStack, parScope, block, parScope?.Interp) { }
public object InvokeBlock(VarCtx parentCtx) { var childCtx = new VarCtx(parentCtx, parentCtx, this); return(RunBlock(childCtx)); }
public RuntimeException(object msg, VarCtx ctx) { Message = msg; ThrowContext = ctx; }
public static object DeclareVar(VarCtx varCtx, string key, object value) { return(varCtx.Vars[key] = value); }