public Item Invoke(SymbolSpace space, List <Item> items) { if (!this.EvaluateDemands(items)) { throw new Exception("Failed demands."); } var result = this.Function(space, items); if (result == null) { if (this.ReturnType != ItemType.None && this.ReturnType != ItemType.Any) { throw new Exception("Non-void function returned void."); } } else { if (this.ReturnType != ItemType.Something && this.ReturnType != ItemType.Any && this.ReturnType != result.ItemType) { throw new Exception("Function returned improper type."); } } return(result); }
/// <summary> /// Updates the weight of <paramref name="symbol" /> based on the provided <paramref name="weightModifier" />. /// The modification can be either positive or negative. /// This function runs in O(weightModifier * height). Expected is E(height). /// </summary> private void UpdateSymbolInternal(SymbolSpace symbol, int weightModifier) { // Find out if the symbol is in the tree uint index; if (!_map.TryGetValue(symbol, out index)) { index = AddNewSymbol(symbol); ToDot(DotOp.AddSymbol, index, 0, 0, symbol.Symbol); } if (weightModifier < 0 && _entries[index].Weight < -weightModifier) { throw new ArgumentOutOfRangeException("weightModifier"); } if (weightModifier < 0) { DecreaseIndex(index, Math.Abs(weightModifier)); } else { IncreaseIndex(index, weightModifier); } }
public static void Setup() { var invo = new InvokeableItem(); var fn = new Invokeable { ReturnType = ItemType.Space, Demands = InvokeableUtils.MakeDemands( InvokeableUtils.DemandType(0, ItemType.List), args => (args[0] as ListItem).Expression.HasEvenLength(), args => (args[0] as ListItem).Expression .GroupingSelect(2) .All(pair => pair[0].ItemType == ItemType.Symbol)), Function = (space, args) => { var newSpace = new SymbolSpace(space); var symbolValuePairs = (args[0] as ListItem).Expression.GroupingSelect(2); foreach (var pair in symbolValuePairs) { var symbol = pair[0] as SymbolItem; newSpace.Bind(symbol.Name, pair[1]); } return(new SymbolSpaceItem(newSpace)); } }; invo.AddInvokeable(fn); globalSpace.Bind("make-space", invo); }
/// <summary> /// Adds the new symbol to the list with a weight of zero as the last entry. /// This function runs in O(map). /// </summary> /// <returns> /// The index to the new symbol. /// </returns> private uint AddNewSymbol(SymbolSpace symbol) { var oldMinWeightEntry = MinWeightEntry; var movedSymbol = _entries[oldMinWeightEntry].Symbol; { var newEntries = new Entry[_entries.Length + 2]; Array.Copy(_entries, newEntries, _entries.Length); _entries = newEntries; } // Copy the previous entry _entries[oldMinWeightEntry + 1] = _entries[oldMinWeightEntry]; // Make the old entry an internal node _entries[oldMinWeightEntry].FirstChildIndex = oldMinWeightEntry + 1; _entries[oldMinWeightEntry].Symbol.Clear(); // Update the new entry _entries[oldMinWeightEntry + 2].Symbol = symbol; _entries[oldMinWeightEntry + 2].Height = 1; // Set parents _entries[oldMinWeightEntry + 1].ParentIndex = oldMinWeightEntry; _entries[oldMinWeightEntry + 2].ParentIndex = oldMinWeightEntry; RecomputeHeightsFrom(oldMinWeightEntry); _map[movedSymbol] = oldMinWeightEntry + 1; _map[symbol] = oldMinWeightEntry + 2; return(oldMinWeightEntry + 2); }
private List <Item> Flatten(SymbolSpace space) { var current = new List <Item>(this.Expression); List <Item> output; Func <List <Item>, bool> anyNonquoted = l => l .Select(item => item as EvaluateableItem) .Where(item => item != null) .Count(item => !item.IsQuoted) > 0; // Evaluate all non-quoted while there are still non-quoted. while (anyNonquoted(current)) { output = new List <Item>(); foreach (var item in current) { Item evaluated; if (item is EvaluateableItem) { var evaluateable = item as EvaluateableItem; evaluated = evaluateable.IsQuoted ? evaluateable : evaluateable.Evaluate(space); } else { evaluated = item; } output.Add(evaluated); } current = output; } // Evaluate all quoted items *ONCE*. output = new List <Item>(); foreach (var item in current) { Item evaluated; if (item is EvaluateableItem) { var evaluateable = item as EvaluateableItem; evaluated = evaluateable.IsQuoted ? evaluateable.Evaluate(space) : evaluateable; } else { evaluated = item; } output.Add(evaluated); } return(output); }
private static Item Deref(SymbolSpace space, SymbolItem symbol) { var reference = space.Lookup(symbol.Name); return(reference is EvaluateableItem ? (reference as EvaluateableItem).Quote() : reference); }
public override Item Evaluate(SymbolSpace space) { if (this.IsQuoted) { this.IsQuoted = false; return(this); } return(this.Flatten(this.BoundSpace ?? space)); }
/// <summary> /// Returns the weight of <paramref name="symbol" /> in the tree. /// This function runs in O(map). /// </summary> /// <returns>The weight of the symbol or zero if not found.</returns> private uint GetWeightInternal(SymbolSpace symbol) { uint index; if (_map.TryGetValue(symbol, out index)) { return(_entries[index].Weight); } return(0); }
/// <summary> /// Returns the level in the tree <paramref name="symbol" /> occurs at. /// This function runs in O(map + level). /// </summary> private uint GetLevelInternal(SymbolSpace symbol) { uint level = 0; for (var index = _map[symbol]; index != Root; index = _entries[index].ParentIndex) { ++level; } return(level); }
public Item Invoke(SymbolSpace space, List <Item> items) { foreach (var invokeable in this.invokeables) { if (invokeable.EvaluateDemands(items)) { return(invokeable.Invoke(space, items)); } } throw new Exception("No matching signature in invokeable collection."); }
/// <summary> /// Retrieves a symbol. If the bit sequence from <paramref name="bitReader"/> /// identifies a symbol literal, <paramref name="symbolReader"/> is called. /// </summary> public TSymbolType GetSymbol(ReadBitDelegate bitReader, ReadSymbolDelegate <TSymbolType> symbolReader) { SymbolSpace result = GetSymbolInternal(bitReader); if (result.IsValid) { UpdateSymbolInternal(result, 1); UpdateSymbolInternal(SymbolSpace.NotYetTransmitted, GetTweak(result.Symbol, false)); return(result.Symbol); } result = symbolReader(); UpdateSymbolInternal(SymbolSpace.NotYetTransmitted, GetTweak(result.Symbol, true)); UpdateSymbolInternal(result, 1); return(result.Symbol); }
public Item Flatten(SymbolSpace space) { var current = space.Lookup(this.Name); while (current.ItemType == ItemType.Symbol) { var symbol = (SymbolItem)current; if (symbol.IsQuoted) { break; } current = symbol.Evaluate(space); } return(current); }
public static void SetupBuiltins(SymbolSpace space) { globalSpace = space; Unless.Setup(); When.Setup(); If.Setup(); Let.Setup(); Equal.Setup(); Bind.Setup(); DerefSymbol.Setup(); Evaluate.Setup(); In.Setup(); Print.Setup(); Negate.Setup(); Quote.Setup(); Unquote.Setup(); MakeSpace.Setup(); Def.Setup(); Get.Setup(); Add.Setup(); Defn.Setup(); }
public override Item Evaluate(SymbolSpace space) { if (this.IsQuoted) { this.IsQuoted = false; return(this); } var exp = this.Flatten(space); var head = exp.First() as InvokeableItem; var tail = exp.Skip(1).ToList(); if (head == null) { throw new Exception(); } var result = head.Invoke(space, tail); return(result); }
public static void Setup() { const int typeIndex = 0; const int paramsIndex = 1; const int bodyIndex = 2; Func <Item, List <Tuple <Item, Item> > > groupArguments = l => (l as ListItem).Expression .GroupingSelect(2, xs => new Tuple <Item, Item>(xs[0], xs[1])); Func <List <Item>, ListItem> getParams = args => (args[paramsIndex] as ListItem); // now to the meat of things var invo = new InvokeableItem(); var fn = new Invokeable { ReturnType = ItemType.Invokeable, Demands = InvokeableUtils.MakeDemands( InvokeableUtils.DemandTypes(ItemType.Type, ItemType.List, ItemType.List), args => args.Count == 3, args => getParams(args).Expression.HasEvenLength(), args => groupArguments(getParams(args)).All(pair => pair.Item1.ItemType == ItemType.Symbol && pair.Item2.ItemType == ItemType.Type) ), Function = (space, args) => { var returnType = args[typeIndex] as TypeItem; var argumentList = groupArguments(args[paramsIndex]); var body = args[bodyIndex] as ListItem; var argumentTypes = argumentList .Select(argument => (argument.Item2 as TypeItem).Type) .ToArray(); var resultingInvokeable = new InvokeableItem(); resultingInvokeable.AddInvokeable(new Invokeable() { ReturnType = returnType.Type, Demands = InvokeableUtils.MakeDemands(InvokeableUtils.DemandTypes(argumentTypes)), // create symbol space, // bind fnargs, // evaluate body with new symbol space Function = (fnspace, fnargs) => { var newSpace = new SymbolSpace(space); for (var index = 0; index < fnargs.Count; index++) { newSpace.Bind( (argumentList[index].Item1 as SymbolItem).Name, fnargs[index]); } body = body.Unquote() as ListItem; return(body.Evaluate(newSpace)); } }); return(resultingInvokeable); } }; invo.AddInvokeable(fn); globalSpace.Bind("=>", invo); }
public SymbolSpaceItem(SymbolSpace space) : base(ItemType.Space) { this.Space = space; }
public SymbolItem(string name, SymbolSpace space) : base(ItemType.Symbol) { this.Name = name; this.BoundSpace = space; }
/// <summary> /// Converts writing <paramref name="symbol" /> to writing based on its corresponding index in the tree. /// </summary> private void WriteCodeInternal(SymbolSpace symbol, WriteBitDelegate bitWriter) { WriteCode(_map[symbol], bitWriter); }
public abstract Item Evaluate(SymbolSpace space);