Read about our upcoming Code of Conduct on this issue

This instance was upgraded to Heptapod 0.28.0 today

ZapfAssembler.cs 4.38 KB
Newer Older
1
/* Copyright 2010-2018 Jesse McGrew
2
 * 
Jesse McGrew's avatar
Jesse McGrew committed
3
 * This file is part of ZILF.
4
 * 
Jesse McGrew's avatar
Jesse McGrew committed
5
 * ZILF is free software: you can redistribute it and/or modify it
6
7
8
9
 * under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
Jesse McGrew's avatar
Jesse McGrew committed
10
 * ZILF is distributed in the hope that it will be useful, but
11
12
13
14
15
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
Jesse McGrew's avatar
Jesse McGrew committed
16
 * along with ZILF.  If not, see <http://www.gnu.org/licenses/>.
17
18
19
 */

using System;
Jesse McGrew's avatar
Jesse McGrew committed
20
using System.Diagnostics.CodeAnalysis;
21
using System.IO;
22
23
using Zapf.Parsing;
using Zapf.Parsing.Diagnostics;
24
using Zilf.Common;
25
26
27

namespace Zapf
{
28
    [Obsolete("Use " + nameof(IFileSystem) + " instead.")]
29
    class OpeningFileEventArgs : EventArgs
30
    {
31
        public OpeningFileEventArgs(string filename, bool writing)
32
        {
33
34
            FileName = filename;
            Writing = writing;
35
36
        }

37
        public string FileName { get; }
38

39
        public bool Writing { get; }
40

41
        public Stream? Stream { get; set; }
42
43
    }

44
    [Obsolete("Use " + nameof(IFileSystem) + " instead.")]
45
    class CheckingFilePresenceEventArgs : EventArgs
46
    {
47
        public CheckingFilePresenceEventArgs(string filename) => FileName = filename;
48

49
        public string FileName { get; }
50

51
52
53
        public bool? Exists { get; set; }
    }

54
55
    class InitializingContextEventArgs : EventArgs
    {
56
        public InitializingContextEventArgs(Context ctx) => Context = ctx;
57

58
        public Context Context { get; }
59
60
    }

Jesse McGrew's avatar
Jesse McGrew committed
61
    readonly struct AssemblyResult
62
    {
63
        public AssemblyResult(bool success, Context? context)
64
65
66
67
68
69
70
        {
            Success = success;
            Context = context;
        }

        public static readonly AssemblyResult Failed = new AssemblyResult(false, null);

Jesse McGrew's avatar
Jesse McGrew committed
71
        [MemberNotNullWhen(true, nameof(Context))]
72
        public bool Success { get; }
73
        public Context? Context { get; }
74
75
    }

76
    sealed class ZapfAssembler
77
    {
78
        public IFileSystem FileSystem { get; set; } = PhysicalFileSystem.Instance;
79

80
        public event EventHandler<InitializingContextEventArgs>? InitializingContext;
81

82
        Context InitializeContext(string inputFileName, string? outputFileName)
83
        {
84
            var ctx = new Context
85
86
87
88
            {
                Quiet = true,
                InFile = inputFileName,
                OutFile = outputFileName,
89
90
                DebugFile = Path.ChangeExtension(outputFileName, ".dbg"),
                FileSystem = FileSystem
91
92
            };

93
94
95
96
97
98
99
100
101
102
            var handler = InitializingContext;
            if (handler != null)
            {
                var args = new InitializingContextEventArgs(ctx);
                handler(this, args);
            }

            return ctx;
        }

103
        public AssemblyResult Assemble(string inputFileName, string outputFileName)
104
        {
105
            using var ctx = InitializeContext(inputFileName, outputFileName);
106

107
108
109
110
            //XXX redirect log messages

            // set up OpcodeDict and GlobalSymbols for the target version
            ctx.OpcodeDict = Program.MakeOpcodeDict(ctx.ZVersion, ctx.InformMode);
111
            ctx.Restart();
112
113
114
115
116
117
118
119
120
121
122
123
124
125

            // perform assembly
            try
            {
                bool restart;
                do
                {
                    restart = false;
                    try
                    {
                        Program.Assemble(ctx);
                    }
                    catch (RestartException)
                    {
126
                        ctx.Restart();
127
128
129
130
131
                        restart = true;
                    }
                    catch (FatalError fer)
                    {
                        ctx.HandleFatalError(fer);
132
                        return AssemblyResult.Failed;
133
134
135
136
137
138
                    }
                } while (restart);

                //XXX find abbreviations?

                // done
139
                return new AssemblyResult(ctx.ErrorCount == 0, ctx);
140
141
142
143
144
145
146
147
148
            }
            finally
            {
                ctx.CloseOutput();
                ctx.CloseDebugFile();
            }
        }
    }
}