public Frame(Stringish id, SourceReference source_ref, Context context, Frame container) { SourceReference = source_ref; Context = Context.Prepend(this, context); Container = container ?? this; Id = id; }
public Stringish RenderTrace(Stringish prefix) { var writer = new System.IO.StringWriter(); var seen = new Dictionary <SourceReference, bool>(); SourceReference.Write(writer, prefix.ToString(), seen); return(new SimpleStringish(writer.ToString())); }
private static bool VerifySymbol(Stringish strish, ReportError error) { var str = strish.ToString(); if (str.Length < 1) { error("An attribute name cannot be empty."); return(false); } switch (Char.GetUnicodeCategory(str[0])) { case UnicodeCategory.LowercaseLetter: case UnicodeCategory.OtherLetter: break; default: error(String.Format("The name “{0}” is unbecoming of an attribute; it cannot start with “{1}”.", str, str[0])); return(false); } for (var it = 1; it < str.Length; it++) { if (str[it] == '_') { continue; } switch (Char.GetUnicodeCategory(str[it])) { case UnicodeCategory.DecimalDigitNumber: case UnicodeCategory.LetterNumber: case UnicodeCategory.LowercaseLetter: case UnicodeCategory.OtherLetter: case UnicodeCategory.OtherNumber: case UnicodeCategory.TitlecaseLetter: case UnicodeCategory.UppercaseLetter: continue; default: error(String.Format("The name “{0}” is unbecoming of an attribute; it cannot contain “{1}”.", str, str[it])); return(false); } } return(true); }
public static bool VerifySymbol(Stringish strish) { return(VerifySymbol(strish.ToString())); }
void LookupString(Frame frame, string name, ConsumeString consume) { var lookup = new Lookup(task_master, source_ref, new [] { name }, Context.Prepend(frame, null)); lookup.Notify(result => { if (result is Stringish) { var str = result.ToString(); consume(str); } else { task_master.ReportOtherError(source_ref, String.Format("Expected “{0}” to be a string. Got {1} instead.", name, Stringish.NameForType(result.GetType()))); } }); }
private void HandleTransformations(object result) { if (result is Frame) { var input = (Frame)result; Interlocked.Add(ref interlock, (int)input.Count); foreach (var name in input.GetAttributeNames()) { input.GetOrSubscribe(name, HandleTransformation); } if (Interlocked.Decrement(ref interlock) == 0) { task_master.Slot(this); } } else { task_master.ReportOtherError(source_ref, String.Format("Expected “transformations” to be a frame. Got {0} instead.", Stringish.NameForType(result.GetType()))); } }
private void HandleArgs(object result) { if (result is Frame) { var input = (Frame)result; Interlocked.Add(ref interlock, (int)input.Count); this.input = new string[input.Count]; var index = 0; foreach (var name in input.GetAttributeNames()) { var target_index = index++; input.GetOrSubscribe(name, arg => { if (arg is Stringish) { this.input[target_index] = arg.ToString(); if (Interlocked.Decrement(ref interlock) == 0) { task_master.Slot(this); } } else { task_master.ReportOtherError(source_ref, String.Format("Expected “args” to contain strings. Got {0} instead.", Stringish.NameForType(arg.GetType()))); } }); } if (Interlocked.Decrement(ref interlock) == 0) { task_master.Slot(this); } } else { task_master.ReportOtherError(source_ref, String.Format("Expected “args” to be a frame. Got {0} instead.", Stringish.NameForType(result.GetType()))); } }
private void HandleArg(object result) { if (result is Stringish) { input = result.ToString(); if (Interlocked.Decrement(ref interlock) == 0) { task_master.Slot(this); } } else { task_master.ReportOtherError(source_ref, String.Format("Expected type “Str” but got “{0}”.", Stringish.NameForType(result.GetType()))); } }
public static bool VerifySymbol(Stringish strish) { return(VerifySymbol(strish, error_msg => {})); }
private void GenerateLookupPermutation(Generator generator, LoadableValue context, LookupCache cache, int index, LoadableCache[] values, LoadableValue source_reference, Block block) { if (index >= values.Length) { block(context, cache); generator.DebugPosition(this); return; } var labels = new Label[values[index].Types.Length]; for (var it = 0; it < labels.Length; it++) { labels[it] = generator.Builder.DefineLabel(); values[index].Value.Load(generator); generator.Builder.Emit(OpCodes.Isinst, values[index].Types[it]); generator.Builder.Emit(OpCodes.Brtrue, labels[it]); } generator.EmitTypeError(source_reference, String.Format("Expected type {0} for “{1}”, but got {2}.", String.Join(" or ", from t in values[index].Types select Stringish.NameForType(t)), values[index].NameInfo.Name, "{0}"), values[index].Value); for (var it = 0; it < labels.Length; it++) { generator.Builder.MarkLabel(labels[it]); var sub_cache = new LookupCache(cache); sub_cache[values[index].NameInfo] = new AutoUnboxValue(values[index].Value, values[index].Types[it]); var builder = generator.Builder; GenerateLookupPermutation(generator, context, sub_cache, index + 1, values, source_reference, block); generator.Builder = builder; } }
internal void GenerateLookupCache(Generator generator, IEnumerable <Tuple <RestrictableType, Generator.ParameterisedBlock <Generator.ParameterisedBlock <LoadableValue> > > > specials, LookupCache current, LoadableValue source_reference, LoadableValue context, LoadableValue self_frame, Block block) { generator.DebugPosition(this); var lookup_results = new List <LoadableCache>(); if (specials != null) { var child_context = generator.MakeField("anon_ctxt", typeof(Context)); var child_frame = generator.MakeField("anon_frame", typeof(MutableFrame)); generator.Builder.Emit(OpCodes.Ldarg_0); generator.LoadTaskMaster(); source_reference.Load(generator); context.Load(generator); self_frame.Load(generator); generator.Builder.Emit(OpCodes.Newobj, typeof(MutableFrame).GetConstructors()[0]); generator.Builder.Emit(OpCodes.Stfld, child_frame.Field); generator.Builder.Emit(OpCodes.Ldarg_0); child_frame.Load(generator.Builder); context.Load(generator.Builder); generator.Builder.Emit(OpCodes.Call, typeof(Context).GetMethod("Prepend", new[] { typeof(Frame), typeof(Context) })); generator.Builder.Emit(OpCodes.Stfld, child_context.Field); // Promote the context with the specials to proper status context = child_context; foreach (var entry in specials) { var next = generator.DefineState(); var field = generator.MakeField("special$" + entry.Item1.Name, typeof(object)); // The types that we might allow are a superset of the ones we // might actually see. So, build a set of the ones we see. Type known_types = 0; entry.Item2(result => { child_frame.Load(generator.Builder); generator.Builder.Emit(OpCodes.Ldstr, entry.Item1.Name); generator.LoadReboxed(result, typeof(object)); generator.Builder.Emit(OpCodes.Call, typeof(MutableFrame).GetMethod("Set", new[] { typeof(string), typeof(object) })); generator.CopyField(result, field); generator.JumpToState(next); known_types |= AstTypeableNode.TypeFromClrType(result.BackingType); }); generator.MarkState(next); lookup_results.Add(new LoadableCache(field, entry.Item1.RestrictedType & known_types, entry.Item1, entry.Item1.MustUnbox)); } } var base_lookup_cache = new LookupCache(current); var all_children = new List <NameInfo>(); foreach (var info in Children.Values) { if (info == null) { continue; } info.AddAll(all_children); } if (current != null) { string narrow_error = null; foreach (var info in all_children) { var current_narrow_error = info.CheckValidNarrowing(base_lookup_cache, current); if (narrow_error != null && current_narrow_error != null) { narrow_error = String.Format("{0}\n{1}", narrow_error, current_narrow_error); } else { narrow_error = narrow_error ?? current_narrow_error; } } if (narrow_error != null) { generator.LoadTaskMaster(); source_reference.Load(generator); generator.Builder.Emit(OpCodes.Ldstr, narrow_error); generator.Builder.Emit(OpCodes.Callvirt, typeof(TaskMaster).GetMethod("ReportOtherError", new[] { typeof(SourceReference), typeof(string) })); generator.Builder.Emit(OpCodes.Ldc_I4_0); generator.Builder.Emit(OpCodes.Ret); return; } } var load_count = all_children.Sum(info => info.NeedsLoad(current) ? 1 : 0); if (load_count > 0) { generator.StartInterlock(load_count); lookup_results.AddRange(from info in all_children where info.NeedsLoad(current) select info.Load(generator, source_reference, context)); var state = generator.DefineState(); generator.SetState(state); generator.DecrementInterlock(generator.Builder); var end_label = generator.Builder.DefineLabel(); generator.Builder.Emit(OpCodes.Brfalse, end_label); generator.Builder.Emit(OpCodes.Ldc_I4_0); generator.Builder.Emit(OpCodes.Ret); generator.Builder.MarkLabel(end_label); generator.JumpToState(state); generator.MarkState(state); } foreach (var lookup_result in lookup_results.Where(x => x.DirectCopy)) { base_lookup_cache[lookup_result.NameInfo] = lookup_result.Value; } foreach (var lookup_result in lookup_results.Where(x => x.SinglyTyped && !x.DirectCopy)) { base_lookup_cache[lookup_result.NameInfo] = new AutoUnboxValue(lookup_result.Value, lookup_result.Types[0]); var label = generator.Builder.DefineLabel(); lookup_result.Value.Load(generator); generator.Builder.Emit(OpCodes.Isinst, lookup_result.Types[0]); generator.Builder.Emit(OpCodes.Brtrue, label); generator.EmitTypeError(source_reference, String.Format("Expected type {0} for “{1}”, but got {2}.", Stringish.NameForType(lookup_result.Types[0]), lookup_result.NameInfo.Name, "{0}"), lookup_result.Value); generator.Builder.MarkLabel(label); } var permutable_caches = lookup_results.Where(x => !x.SinglyTyped && !x.DirectCopy).ToArray(); var old_paths = generator.Paths; generator.Paths = permutable_caches.Aggregate(old_paths, (acc, c) => acc * c.Types.Length); if (generator.Paths > 200 && !combinatorial_explosion) { Console.Error.WriteLine("{0}:{1}:{2}-{3}:{4}: There are {5} type-derived flows in the generated code. This will be slow to compile.", FileName, StartRow, StartColumn, EndRow, EndColumn, generator.Paths); combinatorial_explosion = true; } GenerateLookupPermutation(generator, context, base_lookup_cache, 0, permutable_caches, source_reference, block); generator.Paths = old_paths; }
public ConcatStringish(Stringish head, Stringish tail) { this.head = head; this.tail = tail; chars = head.Length + tail.Length; }
private void HandleFinalResult(object result) { if (result is bool) { Success = true; Console.WriteLine((bool)result ? "True" : "False"); } else if (result is Stringish || result is long || result is bool || result is double) { Success = true; if (output_filename == null) { Console.Write(result); if (!(result is Stringish)) { Console.WriteLine(); } } else { File.WriteAllText(output_filename, result.ToString(), Encoding.UTF8); } } else { Console.Error.WriteLine("Cowardly refusing to print result of type {0}.", Stringish.NameForType(result.GetType())); } }
public bool VerifySymbol(SourceReference source_reference, Stringish strish) { return(VerifySymbol(strish, msg => ReportOtherError(source_reference, msg))); }
public bool VerifySymbol(SourceReference source_reference, Stringish strish) { return(VerifySymbol(source_reference, strish.ToString())); }
internal void IntrinsicDispatch(Generator generator, AstNode node, LoadableValue original, LoadableValue source_reference, Generator.ParameterisedBlock <LoadableValue> block) { var intrinsic = Intrinsics[node]; if (!intrinsic.Item2) { block(original); return; } var types = AstTypeableNode.ClrTypeFromType(intrinsic.Item1); foreach (var type in types) { var next_label = generator.Builder.DefineLabel(); original.Load(generator); generator.Builder.Emit(OpCodes.Isinst, type); generator.Builder.Emit(OpCodes.Brfalse, next_label); var builder = generator.Builder; block(new AutoUnboxValue(original, type)); generator.Builder = builder; generator.Builder.MarkLabel(next_label); } generator.EmitTypeError(source_reference, String.Format("Expected type {0} for {1}, but got {2}.", String.Join(" or ", from t in types select Stringish.NameForType(t)), node.PrettyName, "{0}"), original); }
public bool Has(Stringish name) { return(Has(name.ToString())); }
protected override bool Run() { if (connection == null) { new Lookup(task_master, source_ref, new [] { "connection" }, context).Notify(return_value => { if (return_value is ReflectedFrame) { Object backing = ((ReflectedFrame)return_value).Backing; if (backing is DbConnection) { connection = (DbConnection)backing; if (Interlocked.Decrement(ref interlock) == 0) { task_master.Slot(this); } return; } } task_master .ReportOtherError(source_ref, "Expected “connection” to come from “sql:” import."); }); new Lookup(task_master, source_ref, new [] { "sql_query" }, context).Notify(return_value => { if (return_value is Stringish) { query = return_value.ToString(); if (Interlocked.Decrement(ref interlock) == 0) { task_master.Slot(this); } return; } task_master.ReportOtherError(source_ref, string.Format( "Expected type Str for “sql_query”, but got {0}.", Stringish.NameForType(return_value.GetType()))); }); new Lookup(task_master, source_ref, new [] { "sql_row_tmpl" }, context).Notify(return_value => { if (return_value is Template) { row_tmpl = (Template)return_value; if (Interlocked.Decrement(ref interlock) == 0) { task_master.Slot(this); } return; } task_master.ReportOtherError(source_ref, string.Format( "Expected type Template for “sql_row_tmpl”, but got {0}.", Stringish.NameForType(return_value.GetType()))); }); if (Interlocked.Decrement(ref interlock) > 0) { return(false); } } try { var command = connection.CreateCommand(); command.CommandType = System.Data.CommandType.Text; command.CommandText = query; var reader = command.ExecuteReader(); if (debug) { Console.WriteLine("SQL Query to {0}: {1}", connection, query); } NameChooser name_chooser = (rs, it) => TaskMaster.OrdinalNameStr(it); var retrievers = new List <Retriever>(); for (int col = 0; col < reader.FieldCount; col++) { var column = col; if (reader.GetName(col) == "ATTRNAME") { name_chooser = (rs, it) => rs.GetString(column); continue; } if (reader.GetName(col).StartsWith("$")) { var attr_name = reader.GetName(col).Substring(1); if (!task_master.VerifySymbol(source_ref, attr_name)) { return(false); } retrievers.Add((rs, frame, _task_master) => frame.Set(attr_name, rs.IsDBNull(column) ? Precomputation.Capture(Unit.NULL) : Lookup.Do(rs.GetString(column).Split('.')))); continue; } Unpacker unpacker; if (!unpackers.TryGetValue(reader.GetFieldType(col), out unpacker)) { task_master .ReportOtherError( source_ref, string.Format( "Cannot convert SQL type “{0}” for column “{1}” into Flabbergast type.", reader.GetFieldType(col), reader.GetName(col))); } if (!task_master.VerifySymbol(source_ref, reader.GetName(col))) { return(false); } retrievers.Add(Bind(reader.GetName(col), col, unpacker)); } var list = new MutableFrame(task_master, source_ref, context, self); for (int it = 1; reader.Read(); it++) { var frame = new MutableFrame(task_master, new JunctionReference(string.Format("SQL template instantiation row {0}", it), "<sql>", 0, 0, 0, 0, source_ref, row_tmpl.SourceReference), Context.Append(list.Context, row_tmpl.Context), list); foreach (var r in retrievers) { r(reader, frame, task_master); } foreach (var name in row_tmpl.GetAttributeNames()) { if (!frame.Has(name)) { frame.Set(name, row_tmpl[name]); } } list.Set(name_chooser(reader, it), frame); } list.Slot(); result = list; return(true); } catch (DataException e) { task_master.ReportOtherError(source_ref, e.Message); return(false); } }
public ComputeValue Get(Stringish name) { return(this[name.ToString()]); }
protected override bool Run() { if (tmpl == null) { new Lookup(task_master, src_ref, names, context).Notify(tmpl_result => { if (tmpl_result is Template) { tmpl = (Template)tmpl_result; if (Interlocked.Decrement(ref interlock) == 0) { task_master.Slot(this); } } else { task_master.ReportOtherError(src_ref, string.Format("Expected “{0}” to be a Template but got {1}.", string.Join(".", names), Stringish.NameForType(tmpl_result.GetType()))); } }); if (Interlocked.Decrement(ref interlock) > 0) { return(false); } } var frame = new MutableFrame(task_master, new JunctionReference("instantiation", "<native>", 0, 0, 0, 0, src_ref, tmpl.SourceReference), Context.Append(context, tmpl.Context), container); foreach (var entry in overrides) { frame.Set(entry.Key, entry.Value); } foreach (var name in tmpl.GetAttributeNames()) { if (!overrides.ContainsKey(name)) { frame.Set(name, tmpl[name]); } } result = frame; return(true); }