/// <summary> /// Load a field of an object /// </summary> /// <param name="tree">Tree to be executed</param> /// <returns>The result of the field</returns> private KObject FieldLoad(KermitAST tree) { KermitAST leftExpr = (KermitAST)tree.GetChild(0); KermitAST field = (KermitAST)tree.GetChild(1); KObject obj = Execute(leftExpr); KObject val; string name; if (field.Type == KermitParser.INDEX) { field = (KermitAST)field.GetChild(0); } if (field.Type == KermitParser.CALL) { name = field.GetChild(0).Text; FunctionSpace fSpace = new FunctionSpace(new FunctionSymbol(leftExpr.Text + "." + name, GlobalScope)); MemorySpace savedSpace = _currentSpace; _stack.Push(fSpace); object[] args = new object[field.ChildCount - 1]; for (int i = 0; i < args.Length; ++i) { KObject ko = Execute((KermitAST)field.GetChild(i + 1)); args[i] = obj is KArray ? ko : ko.Value; } try { _currentSpace = fSpace; val = obj.CallInnerFunction(name, args); } finally { _stack.Pop(); _currentSpace = savedSpace; } } else { name = field.Text; val = obj.GetInnerField(name); } field = (KermitAST)field.Parent; if (field.Type == KermitParser.INDEX) { KermitAST memberTree = (KermitAST)field.GetChild(1); val = LoadItem(val, Execute(memberTree)); if (val == null) { ThrowHelper.TypeError($"'{name}' is not enumerable", StackTrace); } } if (val == null) { ThrowHelper.NoFieldError(obj.Value.GetType().Name, name, StackTrace); } return(val); }
/// <summary> /// Execute a function inside the interpreter /// </summary> /// <param name="function">Function to be executed</param> /// <param name="parameters">Parameters to be passed to a function</param> /// <returns>The result of the function</returns> public override KObject CallFunction(KFunction function, List <KLocal> parameters) { FunctionSymbol fSymbol = function.Value; FunctionSpace fSpace = new FunctionSpace(fSymbol); MemorySpace savedSpace = _currentSpace; _currentSpace = fSpace; if (!function.IsNative) { parameters.ForEach(x => fSpace[x.Name] = x); } KObject result = null; _stack.Push(fSpace); try { if (function.IsNative) { FunctionCallbackInfo cInfo = new FunctionCallbackInfo(parameters, this); ((NativeFunctionSymbol)fSymbol).NativeFunction.SafeExecute(cInfo); result = cInfo.ReturnValue.Value; } else { Execute(fSymbol.BlockAst); } } catch (ReturnValue returnValue) { result = returnValue.Value; } finally { _currentSpace = savedSpace; } _stack.Pop(); return(result); }