-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathdb_compiler.h
284 lines (261 loc) · 8.01 KB
/
db_compiler.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
/* db_compiler.h - definitions for a simple basic compiler
*
* Copyright (c) 2014 by David Michael Betz. All rights reserved.
*
*/
#ifndef __DB_COMPILER_H__
#define __DB_COMPILER_H__
#include <stdio.h>
#include <setjmp.h>
#include "db_types.h"
#include "db_image.h"
#include "db_symbols.h"
#include "db_system.h"
/* program limits */
#define MAXTOKEN 32
/* forward type declarations */
typedef struct ParseTreeNode ParseTreeNode;
typedef struct ExprListEntry ExprListEntry;
/* lexical tokens */
enum {
T_NONE,
_T_FIRST_KEYWORD = 0x100,
T_DEF = _T_FIRST_KEYWORD,
T_VAR,
T_IF,
T_ELSE,
T_FOR,
T_DO,
T_WHILE,
T_CONTINUE,
T_BREAK,
T_GOTO,
T_RETURN,
T_PRINT,
#ifdef USE_ASM
T_ASM,
#endif
_T_NON_KEYWORDS,
T_LE = _T_NON_KEYWORDS, /* '<=' */
T_EQ, /* '==' */
T_NE, /* '!=' */
T_GE, /* '>=' */
T_SHL, /* '<<' */
T_SHR, /* '>>' */
T_AND, /* '&&' */
T_OR, /* '||' */
T_INC, /* '++' */
T_DEC, /* '--' */
T_ADDEQ, /* '+=' */
T_SUBEQ, /* '-=' */
T_MULEQ, /* '*=' */
T_DIVEQ, /* '/=' */
T_REMEQ, /* '%=' */
T_ANDEQ, /* '&=' */
T_OREQ, /* '|=' */
T_XOREQ, /* '^=' */
T_SHLEQ, /* '<<=' */
T_SHREQ, /* '>>=' */
T_IDENTIFIER,
T_NUMBER,
T_STRING,
T_EOL,
T_EOF,
_T_MAX
};
/* block type */
typedef enum {
BLOCK_NONE,
BLOCK_DEF,
BLOCK_IF,
BLOCK_ELSE,
BLOCK_FOR,
BLOCK_WHILE,
BLOCK_DO,
BLOCK_BLOCK
} BlockType;
/* block structure */
typedef struct Block Block;
struct Block {
BlockType type;
union {
struct {
int nxt;
int end;
} IfBlock;
struct {
int end;
} ElseBlock;
struct {
int cont;
int contDefined;
int nxt;
int end;
} LoopBlock;
} u;
};
/* label structure */
typedef struct Label Label;
struct Label {
Label *next;
int placed;
int fixups;
int offset;
char name[1];
};
/* code types */
typedef enum {
CODE_TYPE_MAIN,
CODE_TYPE_FUNCTION
} CodeType;
/* parse context */
typedef struct {
System *sys; /* system context */
ImageHdr *image; /* header of image being constructed */
uint8_t *heapBase; /* code staging buffer (start of heap) */
uint8_t *heapFree; /* next free heap location */
uint8_t *heapTop; /* top of heap */
int lineNumber; /* scan - current line number */
int savedToken; /* scan - lookahead token */
int tokenOffset; /* scan - offset to the start of the current token */
char token[MAXTOKEN]; /* scan - current token string */
VMVALUE value; /* scan - current token integer value */
int inComment; /* scan - inside of a slash/star comment */
Label *labels; /* parse - local labels */
CodeType codeType; /* parse - type of code under construction */
Symbol *codeSymbol; /* parse - symbol table entry of code under construction */
SymbolTable arguments; /* parse - arguments of current function definition */
SymbolTable locals; /* parse - local variables of current function definition */
int localOffset; /* parse - offset to next available local variable */
Block blockBuf[10]; /* parse - stack of nested blocks */
Block *bptr; /* parse - current block */
Block *btop; /* parse - top of block stack */
} ParseContext;
/* partial value type codes */
typedef enum {
VT_RVALUE,
VT_LVALUE
} PVAL;
/* partial value function codes */
enum {
PV_LOAD,
PV_STORE
};
/* parse tree node types */
enum {
NodeTypeGlobalSymbolRef,
NodeTypeLocalSymbolRef,
NodeTypeStringLit,
NodeTypeIntegerLit,
NodeTypeFunctionLit,
NodeTypePreincrementOp,
NodeTypePostincrementOp,
NodeTypeUnaryOp,
NodeTypeBinaryOp,
NodeTypeAssignmentOp,
NodeTypeArrayRef,
NodeTypeFunctionCall,
NodeTypeDisjunction,
NodeTypeConjunction
};
/* parse tree node structure */
struct ParseTreeNode {
int nodeType;
union {
struct {
int valueType;
Symbol *symbol;
int offset;
} symbolRef;
struct {
String *string;
} stringLit;
struct {
VMVALUE value;
} integerLit;
struct {
int offset;
} functionLit;
struct {
int op;
ParseTreeNode *expr;
} unaryOp;
struct {
int increment;
ParseTreeNode *expr;
} incrementOp;
struct {
int op;
ParseTreeNode *left;
ParseTreeNode *right;
} binaryOp;
struct {
ParseTreeNode *array;
ParseTreeNode *index;
} arrayRef;
struct {
ParseTreeNode *fcn;
ExprListEntry *args;
int argc;
} functionCall;
struct {
ExprListEntry *exprs;
} exprList;
} u;
};
/* expression list entry structure */
struct ExprListEntry {
ParseTreeNode *expr;
ExprListEntry *next;
};
/* db_compiler.c */
VMVALUE Compile(System *sys, ImageHdr *image);
void EnterBuiltInSymbols(ParseContext *c);
void InitCodeBuffer(ParseContext *c);
void StartCode(ParseContext *c, CodeType type);
VMVALUE StoreCode(ParseContext *c);
void AddIntrinsic(ParseContext *c, char *name, int index);
String *AddString(ParseContext *c, char *value);
VMVALUE AddStringRef(String *str, int offset);
void *LocalAlloc(ParseContext *c, size_t size);
void Fatal(ParseContext *c, char *fmt, ...);
/* db_statement.c */
void ParseStatement(ParseContext *c, int tkn);
BlockType CurrentBlockType(ParseContext *c);
void CheckLabels(ParseContext *c);
/* db_expr.c */
void ParseRValue(ParseContext *c);
ParseTreeNode *ParseExpr(ParseContext *c);
ParseTreeNode *ParsePrimary(ParseContext *c);
ParseTreeNode *GetSymbolRef(ParseContext *c, char *name);
int IsIntegerLit(ParseTreeNode *node);
/* db_scan.c */
void FRequire(ParseContext *c, int requiredToken);
void Require(ParseContext *c, int token, int requiredToken);
int GetToken(ParseContext *c);
void SaveToken(ParseContext *c, int token);
char *TokenName(int token);
int SkipSpaces(ParseContext *c);
int GetChar(ParseContext *c);
void UngetC(ParseContext *c);
void ParseError(ParseContext *c, char *fmt, ...);
/* db_symbols.c */
void InitSymbolTable(SymbolTable *table);
Symbol *AddGlobal(ParseContext *c, const char *name, StorageClass storageClass, VMVALUE value);
Symbol *AddArgument(ParseContext *c, const char *name, StorageClass storageClass, int value);
Symbol *AddLocal(ParseContext *c, const char *name, StorageClass storageClass, int value);
Symbol *FindSymbol(SymbolTable *table, const char *name);
int IsConstant(Symbol *symbol);
void DumpSymbols(SymbolTable *table, char *tag);
/* db_generate.c */
void code_lvalue(ParseContext *c, ParseTreeNode *expr, PVAL *pv);
void code_rvalue(ParseContext *c, ParseTreeNode *expr);
void rvalue(ParseContext *c, PVAL *pv);
void chklvalue(ParseContext *c, PVAL *pv);
int codeaddr(ParseContext *c);
int putcbyte(ParseContext *c, int v);
int putcword(ParseContext *c, VMWORD v);
int putclong(ParseContext *c, VMVALUE v);
void fixup(ParseContext *c, VMUVALUE chn, VMUVALUE val);
void fixupbranch(ParseContext *c, VMUVALUE chn, VMUVALUE val);
#endif