/// <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> /// Assign a value to a field /// </summary> /// <param name="tree">Tree to be executed</param> /// <param name="value">Value to be set</param> private void FieldAssign(KermitAST tree, KObject value) { KermitAST leftExpr = (KermitAST)tree.GetChild(0); KermitAST field = (KermitAST)tree.GetChild(1); KObject obj = Execute(leftExpr); bool isTree = tree.Type == KermitParser.INDEX || field.Type == KermitParser.INDEX; if (field.Type == KermitParser.INDEX) { obj = obj.GetInnerField(field.GetChild(0).Text); field = (KermitAST)field.GetChild(1); } if (isTree) { object fieldValue = Execute(field).Value; if (obj is KArray) { ((KArray)obj)[(int)fieldValue] = value; } else { object real = obj.Value; Type objType = real.GetType(); MethodInfo info = objType.GetMethod("set_Item"); if (info != null) { info.Invoke(real, new[] { fieldValue, value.Value }); } else { ThrowHelper.AttributeError($"{leftExpr.Text} is not asignable", StackTrace); } } } else if (tree.Type == KermitParser.DOT) { string name = field.Text; if (!obj.SetInnerField(name, value)) { ThrowHelper.NoFieldError(obj.Value.GetType().Name, name, StackTrace); } } }