public override void Init(IokeObject obj) { Runtime runtime = obj.runtime; obj.Kind = "Dict"; obj.Mimics(IokeObject.As(IokeObject.FindCell(runtime.Mixins, "Sequenced"), null), runtime.nul, runtime.nul); obj.RegisterMethod(obj.runtime.NewNativeMethod("returns a hash for the dictionary", new NativeMethod.WithNoArguments("hash", (method, context, message, on, outer) => { outer.ArgumentsDefinition.CheckArgumentCount(context, message, on); return(context.runtime.NewNumber(((Dict)IokeObject.dataOf(on)).dict.GetHashCode())); }))); obj.RegisterMethod(runtime.NewNativeMethod("returns true if the left hand side dictionary is equal to the right hand side dictionary.", new TypeCheckingNativeMethod("==", TypeCheckingArgumentsDefinition.builder() .ReceiverMustMimic(runtime.Dict) .WithRequiredPositional("other") .Arguments, (method, on, args, keywords, context, message) => { Dict d = (Dict)IokeObject.dataOf(on); object other = args[0]; return(((other is IokeObject) && (IokeObject.dataOf(other) is Dict) && d.dict.Equals(((Dict)IokeObject.dataOf(other)).dict)) ? context.runtime.True : context.runtime.False); }))); obj.RegisterMethod(runtime.NewNativeMethod("takes one argument, that should be a default value, and returns a new mimic of the receiver, with the default value for that new dict set to the argument", new TypeCheckingNativeMethod("withDefault", TypeCheckingArgumentsDefinition.builder() .ReceiverMustMimic(obj) .WithRequiredPositional("defaultValue") .Arguments, (method, on, args, keywords, context, message) => { object newDict = IokeObject.Mimic(on, message, context); SetDefaultValue(newDict, IokeObject.As(args[0], context)); return(newDict); }))); obj.RegisterMethod(runtime.NewNativeMethod("creates a new Dict from the arguments provided, combined with the values in the receiver. the arguments provided will override those in the receiver. the rules for arguments are the same as for dict, except that dicts can also be provided. all positional arguments will be added before the keyword arguments.", new TypeCheckingNativeMethod("merge", TypeCheckingArgumentsDefinition.builder() .ReceiverMustMimic(obj) .WithRest("pairsAndDicts") .WithKeywordRest("keywordPairs") .Arguments, (method, on, args, keywords, context, message) => { var newMap = new SaneHashtable(); foreach (DictionaryEntry de in GetMap(on)) { newMap[de.Key] = de.Value; } foreach (object o in args) { if (IokeObject.dataOf(o) is Dict) { foreach (DictionaryEntry de in GetMap(o)) { newMap[de.Key] = de.Value; } } else if (IokeObject.dataOf(o) is Pair) { newMap[Pair.GetFirst(o)] = Pair.GetSecond(o); } else { newMap[o] = context.runtime.nil; } } foreach (var entry in keywords) { string s = entry.Key; object key = context.runtime.GetSymbol(s.Substring(0, s.Length - 1)); object value = entry.Value; if (value == null) { value = context.runtime.nil; } newMap[key] = value; } return(context.runtime.NewDict(newMap)); }))); obj.AliasMethod("merge", "+", null, null); obj.RegisterMethod(runtime.NewNativeMethod("takes one argument, the key of the element to return. if the key doesn't map to anything in the dict, returns the default value", new TypeCheckingNativeMethod("at", TypeCheckingArgumentsDefinition.builder() .ReceiverMustMimic(obj) .WithRequiredPositional("key") .Arguments, (method, on, args, keywords, context, message) => { object result = Dict.GetMap(on)[args[0]]; if (result == null) { return(GetDefaultValue(on, context, message)); } else { return(result); } }))); obj.RegisterMethod(runtime.NewNativeMethod("returns true if this dict is empty, false otherwise", new TypeCheckingNativeMethod.WithNoArguments("empty?", obj, (method, on, args, keywords, context, message) => { return(Dict.GetMap(on).Count == 0 ? context.runtime.True : context.runtime.False); }))); obj.RegisterMethod(runtime.NewNativeMethod("takes one argument, the key to check if it is in the dict.", new TypeCheckingNativeMethod("key?", TypeCheckingArgumentsDefinition.builder() .ReceiverMustMimic(obj) .WithRequiredPositional("key") .Arguments, (method, on, args, keywords, context, message) => { return((Dict.GetMap(on).Contains(args[0])) ? context.runtime.True : context.runtime.False); }))); obj.RegisterMethod(runtime.NewNativeMethod("takes two arguments, the key of the element to set and the value to set it too. returns the value set", new TypeCheckingNativeMethod("[]=", TypeCheckingArgumentsDefinition.builder() .ReceiverMustMimic(obj) .WithRequiredPositional("key") .WithRequiredPositional("value") .Arguments, (method, on, args, keywords, context, message) => { Dict.GetMap(on)[args[0]] = args[1]; return(args[1]); }))); obj.RegisterMethod(runtime.NewNativeMethod("Returns the number of pairs contained in this dict.", new TypeCheckingNativeMethod.WithNoArguments("size", obj, (method, on, args, keywords, context, message) => { return(runtime.NewNumber(Dict.GetMap(on).Count)); }))); obj.RegisterMethod(runtime.NewNativeMethod("Returns a text inspection of the object", new TypeCheckingNativeMethod.WithNoArguments("inspect", obj, (method, on, args, keywords, context, message) => { return(method.runtime.NewText(Dict.GetInspect(on))); }))); obj.RegisterMethod(runtime.NewNativeMethod("Returns a brief text inspection of the object", new TypeCheckingNativeMethod.WithNoArguments("notice", obj, (method, on, args, keywords, context, message) => { return(method.runtime.NewText(Dict.GetNotice(on))); }))); obj.RegisterMethod(runtime.NewNativeMethod("Returns all the keys of this dict", new TypeCheckingNativeMethod.WithNoArguments("keys", obj, (method, on, args, keywords, context, message) => { return(method.runtime.NewSet(Dict.GetKeys(on))); }))); obj.RegisterMethod(runtime.NewNativeMethod("returns a new sequence to iterate over this dictionary", new TypeCheckingNativeMethod.WithNoArguments("seq", obj, (method, on, args, keywords, context, message) => { IokeObject ob = method.runtime.KeyValueIteratorSequence.AllocateCopy(null, null); ob.MimicsWithoutCheck(method.runtime.KeyValueIteratorSequence); ob.Data = new Sequence.KeyValueIteratorSequence(Dict.GetMap(on).GetEnumerator()); return(ob); }))); obj.RegisterMethod(runtime.NewNativeMethod("takes either one or two or three arguments. if one argument is given, it should be a message chain that will be sent to each object in the dict. the result will be thrown away. if two arguments are given, the first is an unevaluated name that will be set to each of the entries in the dict in succession, and then the second argument will be evaluated in a scope with that argument in it. if three arguments is given, the first one is an unevaluated name that will be set to the index of each element, and the other two arguments are the name of the argument for the value, and the actual code. the code will evaluate in a lexical context, and if the argument name is available outside the context, it will be shadowed. the method will return the dict. the entries yielded will be mimics of Pair.", new NativeMethod("each", DefaultArgumentsDefinition.builder() .WithOptionalPositionalUnevaluated("indexOrArgOrCode") .WithOptionalPositionalUnevaluated("argOrCode") .WithOptionalPositionalUnevaluated("code") .Arguments, (method, context, message, on, outer) => { outer.ArgumentsDefinition.CheckArgumentCount(context, message, on); on = runtime.Dict.ConvertToThis(on, message, context); var ls = Dict.GetMap(on); switch (message.Arguments.Count) { case 0: { return(Interpreter.Send(runtime.seqMessage, context, on)); } case 1: { IokeObject code = IokeObject.As(message.Arguments[0], context); foreach (DictionaryEntry o in ls) { context.runtime.interpreter.Evaluate(code, context, context.RealContext, runtime.NewPair(o.Key, o.Value)); } break; } case 2: { IokeObject c = context.runtime.NewLexicalContext(context, "Lexical activation context for Dict#each", context); string name = IokeObject.As(message.Arguments[0], context).Name; IokeObject code = IokeObject.As(message.Arguments[1], context); foreach (DictionaryEntry o in ls) { c.SetCell(name, runtime.NewPair(o.Key, o.Value)); context.runtime.interpreter.Evaluate(code, c, c.RealContext, c); } break; } case 3: { IokeObject c = context.runtime.NewLexicalContext(context, "Lexical activation context for Dict#each", context); string iname = IokeObject.As(message.Arguments[0], context).Name; string name = IokeObject.As(message.Arguments[1], context).Name; IokeObject code = IokeObject.As(message.Arguments[2], context); int index = 0; foreach (DictionaryEntry o in ls) { c.SetCell(name, runtime.NewPair(o.Key, o.Value)); c.SetCell(iname, runtime.NewNumber(index++)); context.runtime.interpreter.Evaluate(code, c, c.RealContext, c); } break; } } return(on); }))); }
public int GetEvaluatedArguments(IokeObject context, IokeObject message, object on, IList argumentsWithoutKeywords, IDictionary <string, object> givenKeywords) { Runtime runtime = context.runtime; IList arguments = message.Arguments; int argCount = 0; foreach (object o in arguments) { if (Message.IsKeyword(o)) { givenKeywords[IokeObject.As(o, context).Name] = Interpreter.GetEvaluatedArgument(((Message)IokeObject.dataOf(o)).next, context); } else if (Message.HasName(o, "*") && IokeObject.As(o, context).Arguments.Count == 1) // Splat { object result = Interpreter.GetEvaluatedArgument(IokeObject.As(o, context).Arguments[0], context); if (IokeObject.dataOf(result) is IokeList) { IList elements = IokeList.GetList(result); foreach (object ox in elements) { argumentsWithoutKeywords.Add(ox); } argCount += elements.Count; } else if (IokeObject.dataOf(result) is Dict) { IDictionary keys = Dict.GetMap(result); foreach (DictionaryEntry me in keys) { givenKeywords[Text.GetText(IokeObject.ConvertToText(me.Key, message, context, true)) + ":"] = me.Value; } } else if (IokeObject.FindCell((IokeObject)result, "asTuple") != runtime.nul) { object tupledValue = Interpreter.Send(runtime.asTuple, context, result); object[] values = Tuple.GetElements(tupledValue); foreach (object val in values) { argumentsWithoutKeywords.Add(val); } argCount += values.Length; } else { IokeObject condition = IokeObject.As(IokeObject.GetCellChain(runtime.Condition, message, context, "Error", "Invocation", "NotSpreadable"), context).Mimic(message, context); condition.SetCell("message", message); condition.SetCell("context", context); condition.SetCell("receiver", on); condition.SetCell("given", result); IList outp = IokeList.GetList(runtime.WithRestartReturningArguments(() => { runtime.ErrorCondition(condition); }, context, new Restart.DefaultValuesGivingRestart("ignoreArgument", runtime.nil, 0), new Restart.DefaultValuesGivingRestart("takeArgumentAsIs", IokeObject.As(result, context), 1) )); foreach (object ox in outp) { argumentsWithoutKeywords.Add(ox); } argCount += outp.Count; } } else { var xx = Interpreter.GetEvaluatedArgument(o, context); argumentsWithoutKeywords.Add(xx); argCount++; } } while (argCount < min || (max != -1 && argCount > max)) { int finalArgCount = argCount; if (argCount < min) { IokeObject condition = IokeObject.As(IokeObject.GetCellChain(runtime.Condition, message, context, "Error", "Invocation", "TooFewArguments"), context).Mimic(message, context); condition.SetCell("message", message); condition.SetCell("context", context); condition.SetCell("receiver", on); condition.SetCell("missing", runtime.NewNumber(min - argCount)); IList newArguments = IokeList.GetList(runtime.WithRestartReturningArguments(() => { runtime.ErrorCondition(condition); }, context, new NewArgumentGivingRestart("provideExtraArguments"), new Restart.DefaultValuesGivingRestart("substituteNilArguments", runtime.nil, min - argCount))); foreach (object ox in newArguments) { argumentsWithoutKeywords.Add(ox); } argCount += newArguments.Count; } else { IokeObject condition = IokeObject.As(IokeObject.GetCellChain(runtime.Condition, message, context, "Error", "Invocation", "TooManyArguments"), context).Mimic(message, context); condition.SetCell("message", message); condition.SetCell("context", context); condition.SetCell("receiver", on); condition.SetCell("extra", runtime.NewList(ArrayList.Adapter(argumentsWithoutKeywords).GetRange(max, finalArgCount - max))); runtime.WithReturningRestart("ignoreExtraArguments", context, () => { runtime.ErrorCondition(condition); }); argCount = max; } } var intersection = new SaneHashSet <string>(givenKeywords.Keys); foreach (string k in keywords) { intersection.Remove(k); } if (krest == null && intersection.Count > 0) { IokeObject condition = IokeObject.As(IokeObject.GetCellChain(runtime.Condition, message, context, "Error", "Invocation", "MismatchedKeywords"), context).Mimic(message, context); condition.SetCell("message", message); condition.SetCell("context", context); condition.SetCell("receiver", on); IList expected = new SaneArrayList(); foreach (string s in keywords) { expected.Add(runtime.NewText(s)); } condition.SetCell("expected", runtime.NewList(expected)); IList extra = new SaneArrayList(); foreach (string s in intersection) { extra.Add(runtime.NewText(s)); } condition.SetCell("extra", runtime.NewList(extra)); runtime.WithReturningRestart("ignoreExtraKeywords", context, () => { runtime.ErrorCondition(condition); }); } return(argCount); }
public static void SetDefaultValue(object on, IokeObject defaultValue) { Dict dict = (Dict)IokeObject.dataOf(on); dict.defaultValue = defaultValue; }