5
5
#ifndef DLANG_COMMAND_HPP
6
6
#define DLANG_COMMAND_HPP
7
7
8
- #include < inttypes.h>
8
+ #include < cinttypes>
9
+ #include < cstdlib>
10
+ #include < variant>
11
+ #include < cstring>
12
+
9
13
10
14
class Command {
15
+ public:
11
16
12
17
// mnemonic instruction
13
18
enum OPCode : uint8_t {
14
19
15
20
// these go in lit header
16
- START_LIT_STRING,
21
+ START_LIT_STRING = 0 ,
17
22
START_LIT_MACRO,
18
23
START_LIT_JSON,
19
24
// END_LIT_STRING, // just use '\0'...
20
25
END_LIT_MACRO,
21
- END_LIT_JSON,
26
+ // END_LIT_JSON, // just use '\0'
27
+
28
+ END_LIT_SECTION,
22
29
23
30
// these can go in macro bodies
24
31
I64_LIT, // push int literal onto stack (too small for header)
@@ -34,14 +41,138 @@ class Command {
34
41
BUILTIN_OP, // operate on stack
35
42
// arg: int16, builtin operator id
36
43
37
- } instr;
44
+ // begin fault table
45
+ ID_NAME, // user-defined identifier name
46
+ // arg: str
47
+ ID_ID, // compiled identifier number
48
+ // arg: int64
49
+ FILE_NAME, // file path
50
+ // arg: str
51
+ DEST_POS, // location in compiled file
52
+ // arg: int64
53
+ SRC_POS, // original file position
54
+ // arg: int64
55
+
56
+ } instr : 8 ;
57
+
58
+ std::variant<uint16_t , int64_t , double , std::string> arg;
59
+
60
+ enum ArgType {
61
+ INT64, INT16, FLOAT, STRING, NO_ARG
62
+ };
63
+
64
+ // used for generating bytecode text format for debugging
65
+ inline std::string to_text () {
66
+ switch (this ->instr ) {
67
+
68
+ // literal defs
69
+ case OPCode::START_LIT_STRING:
70
+ return " String: \" " + std::get<std::string>(this ->arg ) + " \"\n " ;
71
+ case OPCode::START_LIT_JSON:
72
+ return " JSON: " + std::get<std::string>(this ->arg ) + " \n " ;
73
+ case OPCode::START_LIT_MACRO:
74
+ return " Macro: (:\n " ;
75
+ case OPCode::END_LIT_MACRO:
76
+ return " )\n " ;
77
+ case OPCode::END_LIT_SECTION:
78
+ return " #### End Literal Section ####\n " ;
79
+
80
+ // indented bc must be within macro body
81
+ case OPCode::I64_LIT:
82
+ return " \t int64 " + std::to_string (std::get<int64_t >(this ->arg ));
83
+ case OPCode::F64_LIT:
84
+ return " \t double " + std::to_string (std::get<double >(this ->arg ));
85
+ case OPCode::DECL_ID:
86
+ return " \t let " + std::to_string ((uint64_t ) std::get<int64_t >(this ->arg ));
87
+ case OPCode::USE_ID:
88
+ return " \t id $" + std::to_string ((uint64_t ) std::get<int64_t >(this ->arg ));
89
+ case OPCode::USE_LIT:
90
+ return " \t literal #" + std::to_string ((uint64_t ) std::get<int64_t >(this ->arg ));
91
+ case OPCode::BUILTIN_OP:
92
+ // switch (std::get<int16_t>(this->arg)) { ... }
93
+ return " \t OP #" + std::to_string ((uint16_t ) std::get<int16_t >(this ->arg ));
94
+
95
+ // dont care about fault table yet
96
+ default :
97
+ return " " ;
98
+ }
99
+ }
100
+
101
+ // check if it goes in literal header
102
+ inline bool is_lit () const noexcept {
103
+ return this ->instr < OPCode::END_LIT_SECTION;
104
+ }
105
+
106
+ inline ArgType arg_type () {
107
+ switch (this ->instr ) {
108
+ case OPCode::F64_LIT:
109
+ return ArgType::FLOAT;
110
+ case OPCode::I64_LIT: case OPCode::DECL_IDL: case OPCode::USE_ID: case OPCode::USE_LIT:
111
+ case OPCode::ID_ID: case OPCode::SRC_POS: case OPCode::DEST_POS:
112
+ return ArgType::INT64;
113
+ case OPCode::BUILTIN_OP:
114
+ return ArgType::INT16;
115
+ case OPCode::START_LIT_STRING: case OPCode::START_LIT_JSON: case OPCode::ID_NAME: case OPCode::FILE_NAME:
116
+ return ArgType::STRING;
117
+
118
+ default :
119
+ return ArgType::NO_ARG;
120
+ }
121
+ }
38
122
39
- union {
40
- uint64_t i64;
41
- uint16_t i16;
123
+ // copies compiled instruction into ret
124
+ // returns number of chars to read
125
+ std::size_t compile (char *& ret) {
126
+ ArgType t = arg_type ();
127
+ size_t s = 1 ;
128
+ switch (t) {
129
+ case ArgType::STRING: {
130
+ auto &str = std::get<std::string>(this ->arg );
131
+ s += str.size () + 1 ;
132
+ ret = (char *) realloc (ret, s);
133
+ strncpy (ret, (char *) &this ->instr , 1 );
134
+ strcpy (ret + 1 , str.c_str ()); // also copies the '\0'
135
+ break ;
136
+ }
137
+ case ArgType::INT16: {
138
+ s += sizeof (uint16_t );
139
+ ret = (char *) realloc (ret, s);
140
+ uint16_t n = std::get<uint16_t >(this ->arg );
141
+ strncpy (ret, (char *) &this ->instr , 1 );
142
+ strncpy (ret + 1 , (char *) &n, sizeof (uint16_t ));
143
+ break ;
144
+ }
145
+ case ArgType::INT64: {
146
+ s += sizeof (int64_t );
147
+ ret = (char *) realloc (ret, s);
148
+ int64_t n = std::get<int64_t >(this ->arg );
149
+ strncpy (ret, (char *) &this ->instr , 1 );
150
+ strncpy (ret + 1 , (char *) &n, sizeof (int64_t ));
151
+ break ;
152
+ }
153
+ case ArgType::FLOAT: {
154
+ s += sizeof (double );
155
+ ret = (char *) realloc (ret, s);
156
+ double n = std::get<double >(this ->arg );
157
+ strncpy (ret, (char *) &this ->instr , 1 );
158
+ strncpy (ret + 1 , (char *) &n, sizeof (double ));
159
+ break ;
160
+ }
161
+ case ArgType::NO_ARG: {
162
+ ret = (char *) realloc (ret, s);
163
+ strncpy (ret, (char *) &this ->instr , 1 );
164
+ break ;
165
+ }
166
+ default : {
167
+ ret = (char *) realloc (ret, s);
168
+ strncpy (ret, (char *) &this ->instr , 1 );
169
+ break ;
170
+ }
171
+ }
42
172
173
+ return s;
174
+ }
43
175
44
- } arg;
45
176
46
177
};
47
178
0 commit comments