Esempio n. 1
0
        /// <exception cref="CompilerError">Malformed WORD-FLAGS-LIST.</exception>
        public void BuildLateSyntaxTables(BuildLateSyntaxTablesHelpers helpers)
        {
            var actionsTable    = (ITableBuilder)helpers.CompileConstant(ctx.GetStdAtom(StdAtom.ATBL));
            var preactionsTable = (ITableBuilder)helpers.CompileConstant(ctx.GetStdAtom(StdAtom.PATBL));

            helpers.GetGlobal(ctx.GetStdAtom(StdAtom.ACTIONS)).DefaultValue    = actionsTable;
            helpers.GetGlobal(ctx.GetStdAtom(StdAtom.PREACTIONS)).DefaultValue = preactionsTable;

            // word flag table
            if (ctx.GetCompilationFlagOption(StdAtom.WORD_FLAGS_IN_TABLE))
            {
                var wordFlagsListObj = ctx.GetGlobalVal(ctx.GetStdAtom(StdAtom.WORD_FLAGS_LIST)) ?? new ZilList(null, null);

                if (!(wordFlagsListObj is ZilListoidBase wordFlagsList && wordFlagsList is ZilList))
                {
                    throw new CompilerError(CompilerMessages.GVAL_Of_0_Must_Be_1, "WORD-FLAGS-LIST", "a list");
                }

                var wordFlagTable = (ITableBuilder)helpers.CompileConstant(ctx.GetStdAtom(StdAtom.WORD_FLAG_TABLE));
                Debug.Assert(wordFlagTable != null);

                // WORD-FLAGS-LIST may contain duplicates: (W?FOO 96 W?BAR 1 W?FOO 32)
                // only the first appearance of each word will be kept
                var seen     = new HashSet <ZilObject>();
                var filtered = new List <IOperand>();

                while (!wordFlagsList.IsEmpty)
                {
                    if (!wordFlagsList.StartsWith(out ZilObject vword, out ZilObject flags))
                    {
                        throw new CompilerError(CompilerMessages.WORDFLAGSLIST_Must_Have_An_Even_Number_Of_Elements);
                    }

                    if (!seen.Add(vword))
                    {
                        continue;
                    }

                    var nw    = NewParserWord.FromVword(ctx, (ZilHash)vword);
                    var atom  = nw.Atom;
                    var word  = ctx.ZEnvironment.Vocabulary[atom];
                    var zword = helpers.Vocabulary[word];

                    filtered.Add(zword);
                    filtered.Add(helpers.CompileConstant(flags));

                    wordFlagsList = wordFlagsList.GetRest(2);
                    Debug.Assert(wordFlagsList != null);
                }

                wordFlagTable.AddShort((short)filtered.Count);
                foreach (var operand in filtered)
                {
                    wordFlagTable.AddShort(operand);
                }
            }
        }
Esempio n. 2
0
        internal ZilObject NewAddWord([NotNull] ZilAtom name, ZilAtom type, [CanBeNull] ZilObject value, [NotNull] ZilFix flags)
        {
            bool typeProvided;

            if (type == null)
            {
                typeProvided = false;
                type         = ctx.GetStdAtom(StdAtom.TZERO);
            }
            else
            {
                typeProvided = true;
            }

            // find new CLASS by translating TYPE
            var classification = TranslateType(ctx, type);

            // create the word or merge into the existing one
            NewParserWord word;

            if (ctx.ZEnvironment.Vocabulary.TryGetValue(name, out var iword) == false)
            {
                // create it by calling user-provided <MAKE-VWORD name class flags>
                var form = new ZilForm(new ZilObject[]
                {
                    ctx.GetStdAtom(StdAtom.MAKE_VWORD),
                    ZilString.FromString(name.Text),
                    classification,
                    flags
                });

                var vword = (ZilObject)form.Eval(ctx);

                if (vword.StdTypeAtom != StdAtom.VWORD)
                {
                    throw new InterpreterError(InterpreterMessages._0_1_Must_Return_2, "NEW-ADD-WORD", "MAKE-VWORD", "a VWORD");
                }

                word = NewParserWord.FromVword(ctx, (ZilHash)vword);
                ctx.ZEnvironment.Vocabulary.Add(name, word);
            }
            else
            {
                word = (NewParserWord)iword;

                // if old and new CLASS differ in the high bit, error (word class conflict)
                if ((word.Classification & 0x8000) != (classification.Value & 0x8000))
                {
                    throw new InterpreterError(InterpreterMessages._0_New_Classification_1_Is_Incompatible_With_Previous_2, "NEW-ADD-WORD", classification, word.Classification);
                }

                // merge new CLASS into the word
                var combinedClassification = word.Classification | classification.Value;

                if (ctx.ZEnvironment.ZVersion >= 4)
                {
                    if (typeProvided &&
                        (combinedClassification & (dirClass | verbClass)) == (dirClass | verbClass) &&
                        (word.SemanticStuff != null || word.DirId != null) &&
                        value != null)
                    {
                        throw new InterpreterError(InterpreterMessages._0_Word_Would_Be_Overloaded, "NEW-ADD-WORD");
                    }
                }

                word.Classification = combinedClassification;

                // merge new FLAGS into the word
                word.Flags |= flags.Value;
            }

            // store flags
            if (flags.Value != 0)
            {
                var compFlag = ctx.GetCompilationFlagValue("WORD-FLAGS-IN-TABLE");
                if (compFlag != null && compFlag.IsTrue)
                {
                    // prepend .WORD .FLAGS to ,WORD-FLAGS-LIST
                    var wordFlagsList = ctx.GetGlobalVal(ctx.GetStdAtom(StdAtom.WORD_FLAGS_LIST)) ?? new ZilList(null, null);

                    if (wordFlagsList is ZilList list)
                    {
                        list = new ZilList(word.Inner, new ZilList(flags, list));
                        ctx.SetGlobalVal(ctx.GetStdAtom(StdAtom.WORD_FLAGS_LIST), list);
                    }
                    else
                    {
                        throw new InterpreterError(
                                  InterpreterMessages._0_Value_Of_1_Must_Be_2,
                                  "global",
                                  "WORD-FLAGS-LIST",
                                  "a list");
                    }
                }
            }

            if (value != null)
            {
                if (classification.Value == adjClass)
                {
                    // store VALUE as word's ADJ-ID (V3) or SEMANTIC-STUFF (V4+)
                    if (ctx.ZEnvironment.ZVersion >= 4)
                    {
                        word.SemanticStuff = value;
                    }
                    else
                    {
                        word.AdjId = value;
                    }
                }
                else if (classification.Value == dirClass)
                {
                    // store VALUE as word's DIR-ID
                    word.DirId = value;
                }
                else
                {
                    // store VALUE as word's SEMANTIC-STUFF
                    word.SemanticStuff = value;
                }
            }

            return(word.Atom);
        }
Esempio n. 3
0
        public void WriteToBuilder(IWord word, IWordBuilder wb, WriteToBuilderHelpers helpers)
        {
            var  zversion          = ctx.ZEnvironment.ZVersion;
            var  nw                = (NewParserWord)word;
            bool needSemanticStuff = false;

            if (zversion >= 4)
            {
                if (nw.HasClass(dirClass))
                {
                    ConditionalAddByte(wb, word.Atom.Text, helpers.CompileConstant, nw.DirId);
                    wb.AddByte(0);
                }
                else if (!nw.HasClass(verbClass))
                {
                    ConditionalAddShort(wb, word.Atom.Text, helpers.CompileConstant, nw.SemanticStuff);
                }
                else
                {
                    needSemanticStuff = true;
                }
            }
            else
            {
                bool adj = nw.HasClass(adjClass), dir = nw.HasClass(dirClass);
                if (adj || dir)
                {
                    if (adj)
                    {
                        ConditionalAddByte(wb, word.Atom.Text, helpers.CompileConstant, nw.AdjId);
                    }
                    else
                    {
                        wb.AddByte(0);
                    }

                    if (dir)
                    {
                        ConditionalAddByte(wb, word.Atom.Text, helpers.CompileConstant, nw.DirId);
                    }
                    else
                    {
                        wb.AddByte(0);
                    }
                }
                else
                {
                    ConditionalAddShort(wb, word.Atom.Text, helpers.CompileConstant, nw.SemanticStuff);
                }
            }

            bool verbed = false;

            if (nw.HasClass(verbClass))
            {
                var       verbStuff = nw.VerbStuff;
                ZilObject verbStuffId;

                if ((IsVerbPointer(verbStuff) && (verbStuffId = verbStuff.GetPrimitive(ctx)) != null) ||
                    TryGetVerbStuffId(verbStuff, out verbStuffId))
                {
                    if (verbStuffId.StdTypeAtom == StdAtom.VWORD)
                    {
                        verbStuffId = NewParserWord.FromVword(ctx, (ZilHash)verbStuffId).Atom;
                    }
                    var actTableAtom = ZilAtom.Parse("ACT?" + ((ZilAtom)verbStuffId).Text, ctx);
                    var actConstant  = helpers.CompileConstant(actTableAtom);
                    Debug.Assert(actConstant != null);
                    wb.AddShort(actConstant);
                    verbed = true;
                }
            }

            if (!verbed)
            {
                if (zversion == 3)
                {
                    wb.AddShort(0);
                }
                else if (needSemanticStuff)
                {
                    ConditionalAddShort(wb, word.Atom.Text, helpers.CompileConstant, nw.SemanticStuff);
                }
            }

            if (!ctx.GetCompilationFlagOption(StdAtom.WORD_FLAGS_IN_TABLE))
            {
                wb.AddShort((short)nw.Flags);
            }

            if (ctx.GetCompilationFlagOption(StdAtom.ONE_BYTE_PARTS_OF_SPEECH))
            {
                var lowByte  = (byte)(nw.Classification & 0x7f);
                var highByte = (byte)((nw.Classification >> 7) & 0x7f);
                if (lowByte != 0 && highByte != 0)
                {
                    ctx.HandleError(new CompilerError(CompilerMessages.ONEBYTEPARTSOFSPEECH_Loses_Data_For_0, word.Atom.Text));
                }

                if (highByte != 0)
                {
                    wb.AddByte((byte)(highByte | 0x80));
                }
                else
                {
                    wb.AddByte(lowByte);
                }
            }
            else
            {
                wb.AddShort((short)nw.Classification);
            }
        }