Пример #1
0
 public Frame(Stringish id, SourceReference source_ref, Context context, Frame container)
 {
     SourceReference = source_ref;
     Context         = Context.Prepend(this, context);
     Container       = container ?? this;
     Id = id;
 }
Пример #2
0
        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()));
        }
Пример #3
0
        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);
        }
Пример #4
0
 public static bool VerifySymbol(Stringish strish)
 {
     return(VerifySymbol(strish.ToString()));
 }
Пример #5
0
        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())));
                }
            });
        }
Пример #6
0
 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())));
     }
 }
Пример #7
0
 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())));
     }
 }
Пример #8
0
 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())));
     }
 }
Пример #9
0
 public static bool VerifySymbol(Stringish strish)
 {
     return(VerifySymbol(strish, error_msg => {}));
 }
Пример #10
0
        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;
            }
        }
Пример #11
0
        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;
        }
Пример #12
0
 public ConcatStringish(Stringish head, Stringish tail)
 {
     this.head = head;
     this.tail = tail;
     chars     = head.Length + tail.Length;
 }
Пример #13
0
 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()));
     }
 }
Пример #14
0
 public bool VerifySymbol(SourceReference source_reference, Stringish strish)
 {
     return(VerifySymbol(strish, msg => ReportOtherError(source_reference, msg)));
 }
Пример #15
0
 public bool VerifySymbol(SourceReference source_reference, Stringish strish)
 {
     return(VerifySymbol(source_reference, strish.ToString()));
 }
Пример #16
0
        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);
        }
Пример #17
0
 public bool Has(Stringish name)
 {
     return(Has(name.ToString()));
 }
Пример #18
0
        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);
            }
        }
Пример #19
0
 public ComputeValue Get(Stringish name)
 {
     return(this[name.ToString()]);
 }
Пример #20
0
        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);
        }