internal static dynamic Switch(object rawTest, List <SwitchCase> cases, object rawDefaultBlock, object rawScope) { var test = (Expression)rawTest; var defaultBlock = rawDefaultBlock != null ? (Expression)rawDefaultBlock : KumaExpression.KumaBlock(KumaExpression.Default(cases.First().Body.Type)); var scope = (KumaScope)rawScope; dynamic retVal = null; var found = false; var tval = CompilerServices.CompileExpression(test, scope); foreach (var @case in cases.Where(@case => @case.TestValues.Select(testValue => CompilerServices.CompileExpression(testValue, scope)) .Any(xval => Binary(tval, xval, E.Equal, scope)))) { found = true; retVal = CompilerServices.CompileExpression(@case.Body, scope); } if (!found) { retVal = CompilerServices.CompileExpression(defaultBlock, scope); } return(retVal); }
internal static dynamic DefineClassOpen(object rawValue, List <Expression> contents, object rawScope) { var scope = (KumaScope)rawScope; var value = CompilerServices.CompileExpression((Expression)rawValue, scope); if (value == null) { return(null); } var @class = value as KumaClass; if (@class != null) { return(DefineCategory(@class, contents, scope)); } var instance = value as KumaInstance; if (instance != null) { return(DefineCategory(instance.Class, contents, scope)); } var newVal = Kuma.Box(value); return(DefineCategory(((KumaInstance)newVal).Class, contents, scope)); }
internal static dynamic Throw(Expression rawObjExpr, object rawScope) { var scope = rawScope as KumaScope ?? new KumaScope(); var rawObj = CompilerServices.CompileExpression(rawObjExpr, scope); var obj = rawObj as KumaInstance; if (obj == null) { throw new Exception(); } var instance = obj as KumaBoxedInstance; if (instance == null) { throw new KumaException(obj); } var exc = instance.BoxedObject as Exception; if (exc != null) { throw exc; } throw new Exception(); }
internal static dynamic Resolve(object rawName, object rawScope) { if (rawName.GetType() == typeof(InstanceReference)) { var iref = (InstanceReference)rawName; var lval = CompilerServices.CompileExpression(iref.LValue, (KumaScope)rawScope); var gmArgs = new List <Expression> (); gmArgs.Add(Expression.Constant(lval, typeof(object))); return(Dynamic(typeof(object), new InteropBinder.GetMember(iref.Key, (KumaScope)rawScope), gmArgs)); } var name = (string)rawName; var scope = (KumaScope)rawScope; if (name.StartsWith("$") && name != "$:") { scope = scope.GlobalScope; name = name.Substring(1); } if (name.StartsWith("@") && scope["<kuma_context_invokemember>"] != null) { if (name.StartsWith("@@")) { var _val = Resolve("self", scope); if (!(_val is KumaInstance)) { // native object? _val = Kuma.Box((object)_val, scope); } var @class = ((KumaInstance)_val).Class; return (CompilerServices.CompileExpression( KumaExpression.Variable(KumaExpression.InstanceRef(Expression.Constant(@class), Expression.Constant(name.Substring(2)))), scope)); } return (CompilerServices.CompileExpression( KumaExpression.Variable( KumaExpression.InstanceRef(KumaExpression.Variable(Expression.Constant("self")), Expression.Constant(name.Substring(1)))), scope)); } var val = scope[name]; // The cast is needed here because if we get a non-nullable type (such as System.Int32) the check here will throw an exception. // By casting to System.Object we can avoid the exception since it is a boxed value that can be null. if ((object)val == null) { Type type; if ((type = KumaTypeResolver.Resolve(name)) != null) { var @class = KumaClass.BoxClass(type); scope.GlobalScope[@class.Name] = @class; val = @class; } } return(val); }
internal static dynamic Invoke(Type targetType, MethodBase minfo, List <FunctionArgument> args, KumaScope scope) { var isClassMethod = minfo.IsStatic; object target = scope.Variables.ContainsKey("self") ? scope["self"] : isClassMethod ? targetType : targetType.GetConstructor(new Type[] {}).Invoke(null); var arguments = new List <object>(); args.ForEach(arg => { var _val = CompilerServices.CompileExpression(arg.Value, scope); if (_val is KumaString) { _val = (string)_val; } if (_val is KumaNumber) { _val = KumaNumber.Convert((KumaNumber)_val); } arguments.Add(_val); }); while (arguments.Count < minfo.GetParameters().Count()) { arguments.Add(null); } if (minfo.IsConstructor) { var ctor = (ConstructorInfo)minfo; return(ctor.Invoke(arguments.ToArray())); } if (target is KumaInstance && !(target is KumaBoxedInstance) && ((KumaInstance)target).BackingObject != null) { target = ((KumaInstance)target).BackingObject; } dynamic val = null; if (((MethodInfo)minfo).ReturnType != typeof(void)) { val = minfo.Invoke(target, arguments.ToArray()); } else { minfo.Invoke(target, arguments.ToArray()); } return(val); }
internal static dynamic Yield(object function, List <FunctionArgument> values, object scope) { if (!(function is MulticastDelegate)) { return(Call(function, values, scope, KumaExpressionType.Empty, false, false)); } var p = new List <object>(); values.ForEach(val => p.Add(CompilerServices.CompileExpression(val.Value, scope as KumaScope))); return(GenDelegate(function, p, scope)); }
internal static dynamic ObjectMethodChange(object rawSelf, object rawName, bool isRemove, object rawScope) { var scope = (KumaScope)rawScope; var name = (string)rawName; var self = CompilerServices.CompileExpression((Expression)rawSelf, scope); var @class = self as KumaClass; if (@class != null) { if (isRemove) { @class.RemovedMethods.Add(name); } else { @class.UndefinedMethods.Add(name); } } else { var instance = self as KumaInstance; if (instance != null) { if (isRemove) { instance.RemovedMethods.Add(name); } else { instance.UndefinedMethods.Add(name); } } else { var newVal = Kuma.Box(self); if (isRemove) { ((KumaInstance)newVal).RemovedMethods.Add(name); } else { ((KumaInstance)newVal).UndefinedMethods.Add(name); } } } return(null); }
internal static dynamic Sync(object rawName, object rawBlock, object rawScope) { var varName = (string)rawName; var block = (Expression)rawBlock; var scope = (KumaScope)rawScope; var var = scope[varName]; dynamic retVal = null; lock (var) { retVal = CompilerServices.CompileExpression(block, scope); } return(retVal); }
internal static dynamic Access(object container, List <FunctionArgument> args, object rawScope) { var names = new List <string>(); for (var i = 0; i < args.Count; i++) { names.Add(string.Format("index{0}", i)); } var scope = rawScope as KumaScope; var realArgs = new List <object>(); args.ForEach(arg => realArgs.Add(CompilerServices.CompileExpression(arg.Value, scope))); var eArgs = new List <Expression>(); eArgs.Add(Expression.Constant(container, typeof(object))); realArgs.ForEach(arg => eArgs.Add(Expression.Constant(arg))); return(Dynamic(typeof(object), new InteropBinder.GetIndex(scope, new CallInfo(args.Count, names)), eArgs)); }
internal static dynamic DefineModule(object rawName, List <Expression> contents, object rawScope) { lock (_classDefineLock) { var scope = (KumaScope)rawScope; var defineScope = _inClassDefine ? scope : scope.GlobalScope; var name = (string)rawName; var xScope = new KumaScope(scope); var module = new KumaModule { Name = name, Context = scope }; contents.ForEach(content => module.Contents.Add(CompilerServices.CompileExpression(content, xScope))); defineScope[module.Name] = module; return(module); } }
internal static dynamic ConditionalAssign(VariableExpression @var, dynamic value, KumaExpressionType conditionalAssignmentType, bool isConst, object rawScope) { var scope = rawScope as KumaScope; var v = Resolve(CompilerServices.CompileExpression(@var.Name, scope), scope); if (Boolean(v)) { if (conditionalAssignmentType == KumaExpressionType.IfNotNullAssign) { return(Assign(@var, value, E.Assign, isConst, scope)); } } else { if (conditionalAssignmentType == KumaExpressionType.IfNullAssign) { return(Assign(@var, value, E.Assign, isConst, scope)); } } return(v); }
private static dynamic Match(object rawLeft, object rawRight, KumaExpressionType kumaBinaryNodeType, object rawScope) { var scope = (KumaScope)rawScope; var left = CompilerServices.CompileExpression((Expression)rawLeft, scope); var right = CompilerServices.CompileExpression((Expression)rawRight, scope); var KumaName = "=~"; var clrName = InteropBinder.ToClrOperatorName(KumaName); if (left is KumaInstance) { var lo = (KumaInstance)left; DynamicMetaObject dmo = lo.GetMetaObject(Expression.Constant(left)); if (InteropBinder.InvokeMember.SearchForFunction(lo.Class, KumaName, lo, L(Arg(right)), true) != null) { if (kumaBinaryNodeType == KumaExpressionType.NotMatch) { return(!dmo.BindInvokeMember(new InteropBinder.InvokeMember(KumaName, new CallInfo(1), scope), _DMO(DMO(scope), DMO(Arg(right))))); } return(dmo.BindInvokeMember(new InteropBinder.InvokeMember(KumaName, new CallInfo(1), scope), _DMO(DMO(scope), DMO(Arg(right))))); } if (InteropBinder.InvokeMember.SearchForFunction(lo.Class, clrName, lo, L(Arg(right)), true) != null) { if (kumaBinaryNodeType == KumaExpressionType.NotMatch) { return(!dmo.BindInvokeMember(new InteropBinder.InvokeMember(clrName, new CallInfo(1), scope), _DMO(DMO(scope), DMO(Arg(right))))); } return(dmo.BindInvokeMember(new InteropBinder.InvokeMember(clrName, new CallInfo(1), scope), _DMO(DMO(scope), DMO(Arg(right))))); } } var Value = Kuma.Box(left); if (Value.Class != null) { var _dmo = Value.GetMetaObject(Expression.Constant(Value)); if (InteropBinder.InvokeMember.SearchForFunction(Value.Class, KumaName, Value, L(Arg(right)), true) != null) { if (kumaBinaryNodeType == KumaExpressionType.NotMatch) { return(!_dmo.BindInvokeMember(new InteropBinder.InvokeMember(KumaName, new CallInfo(1), scope), _DMO(DMO(scope), DMO(Arg(right))))); } return(_dmo.BindInvokeMember(new InteropBinder.InvokeMember(KumaName, new CallInfo(1), scope), _DMO(DMO(scope), DMO(Arg(right))))); } if (InteropBinder.InvokeMember.SearchForFunction(Value.Class, clrName, Value, L(Arg(right)), true) != null) { if (kumaBinaryNodeType == KumaExpressionType.NotMatch) { return(!_dmo.BindInvokeMember(new InteropBinder.InvokeMember(clrName, new CallInfo(1), scope), _DMO(DMO(scope), DMO(Arg(right))))); } return(_dmo.BindInvokeMember(new InteropBinder.InvokeMember(clrName, new CallInfo(1), scope), _DMO(DMO(scope), DMO(Arg(right))))); } } if (!(left is Regex || right is Regex)) { return(null); } var left1 = left as Regex; var regex = left1 ?? (Regex)right; var str = (left is Regex) ? (string)right : (string)left; if (!regex.Match(str).Success) { return(kumaBinaryNodeType == KumaExpressionType.NotMatch); } var groups = regex.Match(str).Groups; foreach (var groupName in regex.GetGroupNames()) { scope[groupName] = groups[groupName].Value; } return(kumaBinaryNodeType == KumaExpressionType.Match); }
internal static dynamic String(object rawEval, object rawScope) { StringBuilder @new; var eval = rawEval as String; var components = eval.Split(new[] { "#{" }, StringSplitOptions.None); if (components.Count() == 1) { return(new KumaString(eval)); } @new = new StringBuilder(components[0]); for (var i = 1; i < components.Count(); i++) { var parts = components[i].Split(new[] { "}" }, StringSplitOptions.None); var expression = parts[0]; var escapeString = false; if (expression != null && expression[0] == ':') { escapeString = true; expression = expression.Substring(1); } if (expression != null) { var scope = (KumaScope)rawScope; var xexpression = string.Format("{0};", expression); var res = KumaParser.Parse(xexpression); Expression block; if (res != null) { block = KumaExpression.KumaBlock(res); } else { return(null); } var myScope = new KumaScope(); var visitor = new VariableNameVisitor(); visitor.Visit(block); visitor.VariableNames.ForEach(name => myScope[name] = scope[name]); var val = CompilerServices.CompileExpression(block, myScope); if (val != null) { string stringVal = val.ToString(); if (escapeString && val is string) { stringVal = string.Format("\"{0}\"", stringVal); } @new.Append(stringVal ?? ""); } else { @new.Append(expression); } } if (parts.Count() > 1) { @new.Append(parts[1]); var j = 2; while (j < parts.Count()) { @new.Append("}"); @new.Append(parts[j++]); } } } return(new KumaString(@new.ToString())); }
internal static dynamic Begin(object rawTryExpression, List <Expression> rescueBlocksRaw, object rawEnsureBlock, object rawElseBlock, object rawScope) { var tryExpression = (Expression)rawTryExpression; var ensureBlock = (Expression)rawEnsureBlock; var elseBlock = (Expression)rawElseBlock; var scope = (KumaScope)rawScope; dynamic retVal = null; var exceptionRaised = false; var ensureRun = false; var rescueBlocks = new List <RescueExpression>(); rescueBlocksRaw.ForEach( rawBlock => { var block = rawBlock as RescueExpression; if (block != null) { rescueBlocks.Add(block); } }); try { retVal = CompilerServices.CompileExpression(tryExpression, scope); } catch (Exception e) { var KumaException = e as KumaException; var exType = KumaException != null ? KumaException.ExceptionClass.Name : e.GetType().Name; var found = false; exceptionRaised = true; foreach (var rescueBlock in rescueBlocks) { var exceptionTypes = new List <string>(); if (!rescueBlock.IsWildcard) { foreach (var type in rescueBlock.ExceptionTypes) { var obj = Resolve(type, scope); var instance = obj as KumaInstance; if (instance != null) { exceptionTypes.Add(instance.Class.Name); } else { var @class = obj as KumaClass; if (@class != null) { exceptionTypes.Add(@class.Name); } var s = obj as string; if (s != null) { exceptionTypes.Add(s); } var ss = obj as KumaString; if (ss != null) { exceptionTypes.Add(ss); } } } } var exMatches = rescueBlock.IsWildcard; if (!exMatches) { if ((from type in exceptionTypes select KumaTypeResolver.Resolve(type) into _exType where _exType != null let __exType = KumaTypeResolver.Resolve(exType) where __exType != null && __exType.IsSubclassOf(_exType) || __exType == _exType select _exType).Any()) { exMatches = true; } } found = exMatches; if (!found) { if (exceptionTypes.Contains(exType)) { found = true; } else { continue; } } var exception = e as KumaException; if (exception != null) { scope[rescueBlock.VarName] = exception.InnerObject; } else { scope[rescueBlock.VarName] = e; } try { retVal = CompilerServices.CompileExpression(rescueBlock.Body, scope); } catch (Exception) { if (ensureBlock == null) { throw; } ensureRun = true; CompilerServices.CompileExpression(ensureBlock, scope); throw; } break; } if (!found) { throw; } } finally { if (!exceptionRaised && elseBlock != null) { CompilerServices.CompileExpression(elseBlock, scope); } if (!ensureRun && ensureBlock != null) { CompilerServices.CompileExpression(ensureBlock, scope); } } return(retVal); }
internal static dynamic DefineCategory(KumaClass @class, List <Expression> contents, object rawScope) { lock (_classDefineLock) { var scope = (KumaScope)rawScope; _inClassDefine = true; _className = @class.Name; scope["self"] = @class; scope[_className] = @class; _currentClassScope = scope; contents.ForEach(content => { if (content is IncludeExpression) { // We only include modules here so make sure this include references a module var names = ((IncludeExpression)content).Names; dynamic module = null; var index = 0; names.ForEach(mname => { if (module != null && (module is KumaModule)) { module = module.Context[mname]; } else if (index == 0) { module = scope[mname]; } index = index + 1; }); if (module != null) { if (module is KumaModule) { ((KumaModule)module).Contents.ForEach(mcon => { if (mcon is KumaFunction) { if ((mcon as KumaFunction).IsSingleton || (mcon as KumaFunction).Name == "new") { KumaClass.AddMethod(@class.ClassMethods, mcon as KumaFunction); } else { KumaClass.AddMethod(@class.InstanceMethods, mcon as KumaFunction); } if (@class.RemovedMethods.Contains((mcon as KumaFunction).Name)) { @class.RemovedMethods.Remove((mcon as KumaFunction).Name); } if (@class.UndefinedMethods.Contains((mcon as KumaFunction).Name)) { @class.UndefinedMethods.Remove((mcon as KumaFunction).Name); } } }); scope.MergeWithScope(module.Context); } else if (module is KumaClass) { scope[((KumaClass)module).Name] = module; } } } }); contents.ForEach(content => { if (!(content is IncludeExpression)) { var result = CompilerServices.CompileExpression(content, scope); if (result is KumaFunction) { if ((result as KumaFunction).IsSingleton) { KumaClass.AddMethod(@class.ClassMethods, result as KumaFunction); } else { KumaClass.AddMethod(@class.InstanceMethods, result as KumaFunction); } if (@class.RemovedMethods.Contains((result as KumaFunction).Name)) { @class.RemovedMethods.Remove((result as KumaFunction).Name); } if (@class.UndefinedMethods.Contains((result as KumaFunction).Name)) { @class.UndefinedMethods.Remove((result as KumaFunction).Name); } } } }); @class.Context.MergeWithScope(scope); return(@class); } }
internal static dynamic SingletonDefine(Expression rawSingleton, object rawName, object rawArguments, object rawBody, object rawScope) { var scope = (KumaScope)rawScope; var name = (string)rawName; var args = (List <FunctionArgument>)rawArguments; var body = (BlockExpression)rawBody; var function = new KumaFunction(name, args, body, scope); object singleton = CompilerServices.CompileExpression(rawSingleton, scope); if ((singleton is KumaClass)) { var @class = (KumaClass)singleton; if (_inClassDefine) { if (@class.Name == _className) { function.IsSingleton = true; return(function); } KumaClass.AddMethod(@class.InstanceMethods, function); if (@class.RemovedMethods.Contains(name)) { @class.RemovedMethods.Remove(name); } if (@class.UndefinedMethods.Contains(name)) { @class.UndefinedMethods.Remove(name); } } else { KumaClass.AddMethod(@class.InstanceMethods, function); if (@class.RemovedMethods.Contains(name)) { @class.RemovedMethods.Remove(name); } if (@class.UndefinedMethods.Contains(name)) { @class.UndefinedMethods.Remove(name); } } } else if (singleton is KumaInstance) { var @object = (KumaInstance)singleton; @object.SingletonMethods[name] = function; if (@object.RemovedMethods.Contains(name)) { @object.RemovedMethods.Remove(name); } if (@object.UndefinedMethods.Contains(name)) { @object.UndefinedMethods.Remove(name); } } return(function); }
internal static dynamic DefineClass(object rawName, object rawParent, List <Expression> contents, object rawScope) { lock (_classDefineLock) { if (Resolve(rawName, rawScope) != null) { return(DefineCategory(Resolve(rawName, rawScope), contents, rawScope)); } var scope = (KumaScope)rawScope; var defineScope = _inClassDefine ? scope : scope.GlobalScope; _inClassDefine = true; KumaClass parent; if (rawParent == null) { if (scope.GlobalScope["Object"] == null) { scope.GlobalScope["Object"] = Kuma.Box(typeof(object)); } parent = scope.GlobalScope["Object"]; } else { var dParent = Resolve(rawParent as string, scope); if (dParent == null) { _inClassDefine = false; return(null); } if (dParent is Type) { parent = Kuma.Box(dParent); } else { parent = dParent as KumaClass; } if (parent == null) { _inClassDefine = false; return(null); } } var name = (string)rawName; _className = name; var @class = new KumaClass { Name = _className, Parent = parent }; var xScope = new KumaScope(scope); xScope["self"] = @class; xScope[_className] = @class; _currentClassScope = xScope; contents.ForEach(content => { if (content is IncludeExpression) { // We only include modules here so make sure this include references a module var names = ((IncludeExpression)content).Names; dynamic module = null; var index = 0; names.ForEach(mname => { if ((module is KumaModule)) { module = module.Context[mname]; } else if (index == 0) { module = scope[mname]; } index = index + 1; }); if (module != null) { if (module is KumaModule) { ((KumaModule)module).Contents.ForEach(mcon => { if (mcon is KumaFunction) { if ((mcon as KumaFunction).IsSingleton || (mcon as KumaFunction).Name == "new") { KumaClass.AddMethod(@class.ClassMethods, mcon as KumaFunction); } else { KumaClass.AddMethod(@class.InstanceMethods, mcon as KumaFunction); } if (@class.RemovedMethods.Contains((mcon as KumaFunction).Name)) { @class.RemovedMethods.Remove((mcon as KumaFunction).Name); } if (@class.UndefinedMethods.Contains((mcon as KumaFunction).Name)) { @class.UndefinedMethods.Remove((mcon as KumaFunction).Name); } } }); xScope.MergeWithScope(module.Context); } else if (module is KumaClass) { xScope[((KumaClass)module).Name] = module; } } } }); contents.ForEach(content => { if (!(content is IncludeExpression)) { var result = CompilerServices.CompileExpression(content, xScope); if (result is KumaFunction) { if ((result as KumaFunction).IsSingleton || (result as KumaFunction).Name == "new") { KumaClass.AddMethod(@class.ClassMethods, result as KumaFunction); } else { KumaClass.AddMethod(@class.InstanceMethods, result as KumaFunction); } if (@class.RemovedMethods.Contains((result as KumaFunction).Name)) { @class.RemovedMethods.Remove((result as KumaFunction).Name); } if (@class.UndefinedMethods.Contains((result as KumaFunction).Name)) { @class.UndefinedMethods.Remove((result as KumaFunction).Name); } } } }); if ([email protected]("new")) { KumaClass.AddMethod(@class.ClassMethods, new KumaFunction("new", new List <FunctionArgument>(), KumaExpression.KumaBlock( KumaExpression.Return(new List <FunctionArgument> { new FunctionArgument(null, KumaExpression.Variable(Expression.Constant("self"))) }), Expression.Label(KumaParser.ReturnTarget, Expression.Constant(null, typeof(object)))), new KumaScope())); } @class.Context = xScope; defineScope[@class.Name] = @class; _inClassDefine = false; return(@class); } }
internal static dynamic Call(object func, List <FunctionArgument> args, object scope, KumaExpressionType pipeType, bool isOp, bool isPostfix) { if (func == null) { if (((KumaScope)scope).GlobalScope["Kernel"] == null) { // map and check Kernel } throw new NotImplementedException(); } var realArgs = new List <object>(); var names = new List <string>(); var offsetCount = 0; if (func is KumaFunction && !(func is KumaPartialFunction)) { args.ForEach(realArgs.Add); realArgs.Insert(0, scope); if (realArgs.Count() - 1 < names.Count()) { (func as KumaFunction).Arguments.ForEach(arg => { if (arg.HasDefault) { realArgs.Add(new FunctionArgument(arg.Name, arg.DefaultValue)); } }); } offsetCount = 1; if (pipeType != KumaExpressionType.Empty) { realArgs.Add(pipeType); offsetCount = 2; } (func as KumaFunction).SetScope(scope as KumaScope); } else if (func.GetType() == typeof(InstanceReference)) { args.ForEach(realArgs.Add); realArgs.Insert(0, scope); offsetCount = 1; if (pipeType != KumaExpressionType.Empty) { realArgs.Add(pipeType); offsetCount = 2; } var iref = (InstanceReference)func; var lval = CompilerServices.CompileExpression(iref.LValue, (KumaScope)scope); var imArgs = new List <Expression>(); realArgs.ForEach(arg => imArgs.Add(Expression.Constant(arg))); imArgs.Insert(0, Expression.Constant(lval, typeof(object))); if (isOp) { imArgs.Add(Expression.Constant(new KumaUnaryBoolean(isPostfix))); } if (iref.LValue is VariableExpression && CompilerServices.CompileExpression((iref.LValue as VariableExpression).Name, (KumaScope)scope) == "super") { imArgs.Add(Expression.Constant(new KumaDoNotWrapBoolean(true))); } return(Dynamic(typeof(object), new InteropBinder.InvokeMember(iref.Key, new CallInfo(realArgs.Count - offsetCount, names), (KumaScope)scope), imArgs)); } else { // Kuma name logic does not work here args.ForEach(arg => realArgs.Add(CompilerServices.CompileExpression(arg.Value, scope as KumaScope))); } var bArgs = new List <Expression>(); realArgs.ForEach(arg => bArgs.Add(Expression.Constant(ConvertIfNumber(arg)))); bArgs.Insert(0, Expression.Constant(func, typeof(object))); return(Dynamic(typeof(object), new InteropBinder.Invoke(scope as KumaScope, new CallInfo(realArgs.Count - offsetCount, names)), bArgs)); }
internal static dynamic Assign(VariableExpression @var, dynamic value, E type, bool isConst, object rawScope) { var scope = (KumaScope)rawScope; var map = new Dictionary <ExpressionType, ExpressionType> (); map[E.AddAssign] = E.Add; map[E.AndAssign] = E.And; map[E.DivideAssign] = E.Divide; map[E.ExclusiveOrAssign] = E.ExclusiveOr; map[E.LeftShiftAssign] = E.LeftShift; map[E.ModuloAssign] = E.Modulo; map[E.MultiplyAssign] = E.Multiply; map[E.OrAssign] = E.Or; map[E.PowerAssign] = E.Power; map[E.RightShiftAssign] = E.RightShift; map[E.SubtractAssign] = E.Subtract; var incDecMap = new List <ExpressionType> { E.PreIncrementAssign, E.PreDecrementAssign, E.PostIncrementAssign, E.PostDecrementAssign }; if (@var.Name is InstanceReferenceExpression) { var iref = CompilerServices.CompileExpression(@var.Name as InstanceReferenceExpression, scope); var lval = CompilerServices.CompileExpression(iref.LValue, scope); if (map.ContainsKey(type)) { value = CompilerServices.CreateLambdaForExpression( KumaExpression.Binary( Expression.Constant(Resolve(CompilerServices.CompileExpression(iref, scope), scope)), Expression.Constant(value), map[type])) (); } if (incDecMap.Contains(type)) { var gmArgs = new List <Expression> (); gmArgs.Add(Expression.Constant(lval, typeof(object))); if (type == E.PreIncrementAssign || type == E.PreDecrementAssign) { var val = Resolve(CompilerServices.CompileExpression(iref, scope), scope); Assign(@var, 1, type == E.PreIncrementAssign ? E.AddAssign : E.SubtractAssign, false, rawScope); return(val); } Assign(@var, 1, type == E.PostIncrementAssign ? E.AddAssign : E.SubtractAssign, false, rawScope); return(Resolve(CompilerServices.CompileExpression(iref, scope), scope)); } var smArgs = new List <Expression> (); smArgs.Add(Expression.Constant(lval, typeof(object))); smArgs.Add(Expression.Constant(value, typeof(object))); return(Dynamic(typeof(object), new InteropBinder.SetMember(iref.Key, scope), smArgs)); } if (@var.HasSym) { var sym = @var.Sym; var symFound = false; while (scope.ParentScope != null) { scope = scope.ParentScope; if (scope[sym] != null) { symFound = true; break; } } if (!symFound) { scope = (KumaScope)rawScope; } if (map.ContainsKey(type)) { var nvalue = CompilerServices.CreateLambdaForExpression( KumaExpression.Binary(Expression.Constant(ResolveSymbol(sym, scope)), Expression.Constant(value), map[type])) (); scope[sym] = nvalue; return(nvalue); } if (incDecMap.Contains(type)) { if (type == E.PreIncrementAssign || type == E.PreDecrementAssign) { var val = ResolveSymbol(sym, scope); Assign(@var, 1, type == E.PreIncrementAssign ? E.AddAssign : E.SubtractAssign, false, rawScope); return(val); } Assign(@var, 1, type == E.PostIncrementAssign ? E.AddAssign : E.SubtractAssign, false, rawScope); return(ResolveSymbol(sym, scope)); } scope[sym] = value; if (isConst) { scope.Constants.Add(sym.Name); } return(value); } string name = CompilerServices.CompileExpression(@var.Name, scope); if (name.StartsWith("$") && name != "$:") { scope = scope.GlobalScope; name = name.Substring(1); } var found = false; if (name.StartsWith("@")) { if (scope["<kuma_context_invokemember>"] != null) { var ivar = KumaExpression.Variable( KumaExpression.InstanceRef(KumaExpression.Variable(Expression.Constant("self")), Expression.Constant(name.Substring(1)))); if (map.ContainsKey(type)) { value = CompilerServices.CreateLambdaForExpression( KumaExpression.Binary(ivar, Expression.Constant(value), map[type])) (); } var assn = KumaExpression.Assign(KumaExpression.LeftHandValue(ivar), Expression.Constant(value)); return(CompilerServices.CompileExpression(assn, scope)); } found = true; name = name.Substring(1); } if (name == "self") { if (scope["<kuma_context_selfname>"] != null && scope["<kuma_context_selfscope>"] != null && scope["<kuma_context_invokemember>"] != null) { name = scope["<kuma_context_selfname>"]; scope = scope["<kuma_context_selfscope>"]; found = true; } } while (scope.ParentScope != null && !found) { scope = scope.ParentScope; if (scope[name] != null) { found = true; break; } } if (!found) { scope = (KumaScope)rawScope; } if (map.ContainsKey(type)) { var nvalue = CompilerServices.CreateLambdaForExpression( KumaExpression.Binary(Expression.Constant(Resolve(name, scope)), Expression.Constant(value), map[type])) (); scope[name] = nvalue; return(nvalue); } if (incDecMap.Contains(type)) { if (type == E.PostIncrementAssign || type == E.PostDecrementAssign) { var val = Resolve(name, scope); Assign(@var, 1, type == E.PostIncrementAssign ? E.AddAssign : E.SubtractAssign, false, rawScope); return(val); } Assign(@var, 1, type == E.PreIncrementAssign ? E.AddAssign : E.SubtractAssign, false, rawScope); return(Resolve(name, scope)); } scope[name] = value; if (isConst) { scope.Constants.Add(name); } return(value); }
internal static dynamic ParallelAssign( List <ParallelAssignmentExpression.ParallelAssignmentInfo> leftHandValues, List <ParallelAssignmentExpression.ParallelAssignmentInfo> rightHandValues, object rawScope) { var scope = rawScope as KumaScope; var rvalues = new List <object> (); var fval = CompilerServices.CompileExpression(rightHandValues[0].Value as Expression, scope); if (fval is List <object> && !rightHandValues[0].IsWildcard) { rvalues = new List <object> (fval as List <object>); } else { foreach (var rvalue in rightHandValues) { var val = CompilerServices.CompileExpression(rvalue.Value as Expression, scope); if (rvalue.IsWildcard) { if (val is List <object> ) { (val as List <object>).ForEach(value => rvalues.Add(value)); } else { rvalues.Add(val); } } else { rvalues.Add(val); } } } var i = 0; var k = 0; var result = new KumaArray(); foreach (var _lvalue in leftHandValues) { var lvalue = _lvalue.Value; if (i >= rvalues.Count) { break; } k++; if (lvalue is List <ParallelAssignmentExpression.ParallelAssignmentInfo> ) { result.Add(ParallelAssign(lvalue as List <ParallelAssignmentExpression.ParallelAssignmentInfo>, new List <ParallelAssignmentExpression.ParallelAssignmentInfo> { new ParallelAssignmentExpression.ParallelAssignmentInfo { IsWildcard = false, Value = Expression.Constant(rvalues[i++]) } }, scope)); } else if (_lvalue.IsWildcard) { var mvalues = new KumaArray(); for (var j = i; j < rvalues.Count; j++) { mvalues.Add(rvalues[j]); } result.Add(Assign(lvalue as VariableExpression, mvalues, E.Assign, false, rawScope)); break; } else { result.Add(Assign(lvalue as VariableExpression, rvalues[i++], E.Assign, false, rawScope)); } } if (k < leftHandValues.Count) { for (var j = k; j < leftHandValues.Count; j++) { if (leftHandValues[j].Value is List <ParallelAssignmentExpression.ParallelAssignmentInfo> ) { var lvalues = leftHandValues[j].Value as List <ParallelAssignmentExpression.ParallelAssignmentInfo>; for (var l = 0; l < lvalues.Count; l++) { result.Add(Assign(lvalues[l].Value as VariableExpression, null, E.Assign, false, scope)); } } else { result.Add(Assign(leftHandValues[j].Value as VariableExpression, null, E.Assign, false, scope)); } } } return(result.Count > 1 ? result : result[0]); }
internal static dynamic AccessSet(object container, List <FunctionArgument> args, object value, E type, object rawScope) { var map = new Dictionary <ExpressionType, ExpressionType>(); map[E.AddAssign] = E.Add; map[E.AndAssign] = E.And; map[E.DivideAssign] = E.Divide; map[E.ExclusiveOrAssign] = E.ExclusiveOr; map[E.LeftShiftAssign] = E.LeftShift; map[E.ModuloAssign] = E.Modulo; map[E.MultiplyAssign] = E.Multiply; map[E.OrAssign] = E.Or; map[E.PowerAssign] = E.Power; map[E.RightShiftAssign] = E.RightShift; map[E.SubtractAssign] = E.Subtract; var incDecMap = new List <ExpressionType> { E.PreIncrementAssign, E.PreDecrementAssign, E.PostIncrementAssign, E.PostDecrementAssign }; var names = new List <string>(); for (var i = 0; i < args.Count; i++) { names.Add(string.Format("index{0}", i)); } var scope = rawScope as KumaScope; var realArgs = new List <object>(); args.ForEach(arg => realArgs.Add(CompilerServices.CompileExpression(arg.Value, scope))); if (map.ContainsKey(type)) { var nvalue = CompilerServices.CreateLambdaForExpression( KumaExpression.Binary(Expression.Constant(Access(container, args, scope)), Expression.Constant(value), map[type]))(); value = nvalue; } if (incDecMap.Contains(type)) { if (type == E.PostIncrementAssign || type == E.PostDecrementAssign) { var val = Access(container, args, scope); AccessSet(container, args, 1, type == E.PostIncrementAssign ? E.AddAssign : E.SubtractAssign, rawScope); return(val); } AccessSet(container, args, 1, type == E.PreIncrementAssign ? E.AddAssign : E.SubtractAssign, rawScope); return(Access(container, args, scope)); } var eArgs = new List <Expression>(); eArgs.Add(Expression.Constant(container, typeof(object))); realArgs.ForEach(arg => eArgs.Add(Expression.Constant(arg))); eArgs.Add(Expression.Constant(value, typeof(object))); return(Dynamic(typeof(object), new InteropBinder.SetIndex(scope, new CallInfo(args.Count, names)), eArgs)); }