xref: /freebsd/contrib/bearssl/T0/Word.cs (revision 13ea0450a9c8742119d36f3bf8f47accdce46e54)
1 /*
2  * Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining
5  * a copy of this software and associated documentation files (the
6  * "Software"), to deal in the Software without restriction, including
7  * without limitation the rights to use, copy, modify, merge, publish,
8  * distribute, sublicense, and/or sell copies of the Software, and to
9  * permit persons to whom the Software is furnished to do so, subject to
10  * the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be
13  * included in all copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
19  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
20  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22  * SOFTWARE.
23  */
24 
25 using System;
26 using System.Collections.Generic;
27 
28 /*
29  * A "word" is a function with a name. Words can be either native or
30  * interpreted; native words are implemented as some in-compiler special
31  * code.
32  *
33  * Some native words (not all of them) have a C implementation and can
34  * thus be part of the generated C code. Native words with no C
35  * implementation can be used only during compilation; this is typically
36  * the case for words that support the syntax (e.g. 'if').
37  */
38 
39 abstract class Word {
40 
41 	/*
42 	 * The compiler context for this word.
43 	 */
44 	internal T0Comp TC {
45 		get; private set;
46 	}
47 
48 	/*
49 	 * Immediate words are executed immediately when encountered in the
50 	 * source code, even while compiling another word.
51 	 */
52 	internal bool Immediate {
53 		get; set;
54 	}
55 
56 	/*
57 	 * Each word has a unique name. Names are case-sensitive.
58 	 */
59 	internal string Name {
60 		get; private set;
61 	}
62 
63 	/*
64 	 * Words are allocated slot numbers when output code is generated.
65 	 */
66 	internal int Slot {
67 		get; set;
68 	}
69 
70 	/*
71 	 * Each word may have a known stack effect.
72 	 */
73 	internal SType StackEffect {
74 		get; set;
75 	}
76 
77 	internal Word(T0Comp owner, string name)
78 	{
79 		TC = owner;
80 		Name = name;
81 		StackEffect = SType.UNKNOWN;
82 	}
83 
84 	/*
85 	 * Resolving a word means looking up all references to external
86 	 * words.
87 	 */
88 	internal virtual void Resolve()
89 	{
90 	}
91 
92 	/*
93 	 * Execute this word. If the word is native, then its code is
94 	 * run right away; if the word is interpreted, then the entry
95 	 * sequence is executed.
96 	 */
97 	internal virtual void Run(CPU cpu)
98 	{
99 		throw new Exception(String.Format(
100 			"cannot run '{0}' at compile-time", Name));
101 	}
102 
103 	/*
104 	 * All words may have an explicit C implementations. To be part
105 	 * of the generated C code, a word must either be interpreted,
106 	 * or have an explicit C implementation, or both.
107 	 */
108 	internal string CCode {
109 		get; set;
110 	}
111 
112 	/*
113 	 * Get all words referenced from this one. This implies
114 	 * resolving the word.
115 	 */
116 	internal virtual List<Word> GetReferences()
117 	{
118 		return new List<Word>();
119 	}
120 
121 	/*
122 	 * Get all data blocks directly referenced from this one. This
123 	 * implies resolving the word.
124 	 */
125 	internal virtual List<ConstData> GetDataBlocks()
126 	{
127 		return new List<ConstData>();
128 	}
129 
130 	/*
131 	 * Produce the code elements for this word.
132 	 */
133 	internal virtual void GenerateCodeElements(List<CodeElement> dst)
134 	{
135 		throw new Exception("Word does not yield code elements");
136 	}
137 
138 	/*
139 	 * Compute/verify stack effect for this word.
140 	 */
141 	internal virtual void AnalyseFlow()
142 	{
143 	}
144 
145 	/*
146 	 * Get maximum data stack usage for this word. This is the number
147 	 * of extra slots that this word may need on the data stack. If
148 	 * the stack effect is not known, this returns -1.
149 	 */
150 	internal virtual int MaxDataStack {
151 		get {
152 			SType se = StackEffect;
153 			if (!se.IsKnown) {
154 				return -1;
155 			}
156 			if (se.NoExit) {
157 				return 0;
158 			} else {
159 				return Math.Min(0, se.DataOut - se.DataIn);
160 			}
161 		}
162 	}
163 
164 	/*
165 	 * Get maximum return stack usage for this word.
166 	 */
167 	internal virtual int MaxReturnStack {
168 		get {
169 			return 0;
170 		}
171 	}
172 }
173