1#include <errno.h>
2#include <stdbool.h>
3#include <stdio.h>
4#include <string.h>
5
6#include "wren_common.h"
7#include "wren_compiler.h"
8#include "wren_vm.h"
9
10#if WREN_DEBUG_DUMP_COMPILED_CODE
11 #include "wren_debug.h"
12#endif
13
14// This is written in bottom-up order, so the tokenization comes first, then
15// parsing/code generation. This minimizes the number of explicit forward
16// declarations needed.
17
18// The maximum number of local (i.e. not module level) variables that can be
19// declared in a single function, method, or chunk of top level code. This is
20// the maximum number of variables in scope at one time, and spans block scopes.
21//
22// Note that this limitation is also explicit in the bytecode. Since
23// `CODE_LOAD_LOCAL` and `CODE_STORE_LOCAL` use a single argument byte to
24// identify the local, only 256 can be in scope at one time.
25#define MAX_LOCALS 256
26
27// The maximum number of upvalues (i.e. variables from enclosing functions)
28// that a function can close over.
29#define MAX_UPVALUES 256
30
31// The maximum number of distinct constants that a function can contain. This
32// value is explicit in the bytecode since `CODE_CONSTANT` only takes a single
33// two-byte argument.
34#define MAX_CONSTANTS (1 << 16)
35
36// The maximum distance a CODE_JUMP or CODE_JUMP_IF instruction can move the
37// instruction pointer.
38#define MAX_JUMP (1 << 16)
39
40// The maximum depth that interpolation can nest. For example, this string has
41// three levels:
42//
43// "outside %(one + "%(two + "%(three)")")"
44#define MAX_INTERPOLATION_NESTING 8
45
46// The buffer size used to format a compile error message, excluding the header
47// with the module name and error location. Using a hardcoded buffer for this
48// is kind of hairy, but fortunately we can control what the longest possible
49// message is and handle that. Ideally, we'd use `snprintf()`, but that's not
50// available in standard C++98.
51#define ERROR_MESSAGE_SIZE (80 + MAX_VARIABLE_NAME + 15)
52
53typedef enum
54{
55 TOKEN_LEFT_PAREN,
56 TOKEN_RIGHT_PAREN,
57 TOKEN_LEFT_BRACKET,
58 TOKEN_RIGHT_BRACKET,
59 TOKEN_LEFT_BRACE,
60 TOKEN_RIGHT_BRACE,
61 TOKEN_COLON,
62 TOKEN_DOT,
63 TOKEN_DOTDOT,
64 TOKEN_DOTDOTDOT,
65 TOKEN_COMMA,
66 TOKEN_STAR,
67 TOKEN_SLASH,
68 TOKEN_PERCENT,
69 TOKEN_HASH,
70 TOKEN_PLUS,
71 TOKEN_MINUS,
72 TOKEN_LTLT,
73 TOKEN_GTGT,
74 TOKEN_PIPE,
75 TOKEN_PIPEPIPE,
76 TOKEN_CARET,
77 TOKEN_AMP,
78 TOKEN_AMPAMP,
79 TOKEN_BANG,
80 TOKEN_TILDE,
81 TOKEN_QUESTION,
82 TOKEN_EQ,
83 TOKEN_LT,
84 TOKEN_GT,
85 TOKEN_LTEQ,
86 TOKEN_GTEQ,
87 TOKEN_EQEQ,
88 TOKEN_BANGEQ,
89
90 TOKEN_BREAK,
91 TOKEN_CONTINUE,
92 TOKEN_CLASS,
93 TOKEN_CONSTRUCT,
94 TOKEN_ELSE,
95 TOKEN_FALSE,
96 TOKEN_FOR,
97 TOKEN_FOREIGN,
98 TOKEN_IF,
99 TOKEN_IMPORT,
100 TOKEN_AS,
101 TOKEN_IN,
102 TOKEN_IS,
103 TOKEN_NULL,
104 TOKEN_RETURN,
105 TOKEN_STATIC,
106 TOKEN_SUPER,
107 TOKEN_THIS,
108 TOKEN_TRUE,
109 TOKEN_VAR,
110 TOKEN_WHILE,
111
112 TOKEN_FIELD,
113 TOKEN_STATIC_FIELD,
114 TOKEN_NAME,
115 TOKEN_NUMBER,
116
117 // A string literal without any interpolation, or the last section of a
118 // string following the last interpolated expression.
119 TOKEN_STRING,
120
121 // A portion of a string literal preceding an interpolated expression. This
122 // string:
123 //
124 // "a %(b) c %(d) e"
125 //
126 // is tokenized to:
127 //
128 // TOKEN_INTERPOLATION "a "
129 // TOKEN_NAME b
130 // TOKEN_INTERPOLATION " c "
131 // TOKEN_NAME d
132 // TOKEN_STRING " e"
133 TOKEN_INTERPOLATION,
134
135 TOKEN_LINE,
136
137 TOKEN_ERROR,
138 TOKEN_EOF
139} TokenType;
140
141typedef struct
142{
143 TokenType type;
144
145 // The beginning of the token, pointing directly into the source.
146 const char* start;
147
148 // The length of the token in characters.
149 int length;
150
151 // The 1-based line where the token appears.
152 int line;
153
154 // The parsed value if the token is a literal.
155 Value value;
156} Token;
157
158typedef struct
159{
160 WrenVM* vm;
161
162 // The module being parsed.
163 ObjModule* module;
164
165 // The source code being parsed.
166 const char* source;
167
168 // The beginning of the currently-being-lexed token in [source].
169 const char* tokenStart;
170
171 // The current character being lexed in [source].
172 const char* currentChar;
173
174 // The 1-based line number of [currentChar].
175 int currentLine;
176
177 // The upcoming token.
178 Token next;
179
180 // The most recently lexed token.
181 Token current;
182
183 // The most recently consumed/advanced token.
184 Token previous;
185
186 // Tracks the lexing state when tokenizing interpolated strings.
187 //
188 // Interpolated strings make the lexer not strictly regular: we don't know
189 // whether a ")" should be treated as a RIGHT_PAREN token or as ending an
190 // interpolated expression unless we know whether we are inside a string
191 // interpolation and how many unmatched "(" there are. This is particularly
192 // complex because interpolation can nest:
193 //
194 // " %( " %( inner ) " ) "
195 //
196 // This tracks that state. The parser maintains a stack of ints, one for each
197 // level of current interpolation nesting. Each value is the number of
198 // unmatched "(" that are waiting to be closed.
199 int parens[MAX_INTERPOLATION_NESTING];
200 int numParens;
201
202 // Whether compile errors should be printed to stderr or discarded.
203 bool printErrors;
204
205 // If a syntax or compile error has occurred.
206 bool hasError;
207} Parser;
208
209typedef struct
210{
211 // The name of the local variable. This points directly into the original
212 // source code string.
213 const char* name;
214
215 // The length of the local variable's name.
216 int length;
217
218 // The depth in the scope chain that this variable was declared at. Zero is
219 // the outermost scope--parameters for a method, or the first local block in
220 // top level code. One is the scope within that, etc.
221 int depth;
222
223 // If this local variable is being used as an upvalue.
224 bool isUpvalue;
225} Local;
226
227typedef struct
228{
229 // True if this upvalue is capturing a local variable from the enclosing
230 // function. False if it's capturing an upvalue.
231 bool isLocal;
232
233 // The index of the local or upvalue being captured in the enclosing function.
234 int index;
235} CompilerUpvalue;
236
237// Bookkeeping information for the current loop being compiled.
238typedef struct sLoop
239{
240 // Index of the instruction that the loop should jump back to.
241 int start;
242
243 // Index of the argument for the CODE_JUMP_IF instruction used to exit the
244 // loop. Stored so we can patch it once we know where the loop ends.
245 int exitJump;
246
247 // Index of the first instruction of the body of the loop.
248 int body;
249
250 // Depth of the scope(s) that need to be exited if a break is hit inside the
251 // loop.
252 int scopeDepth;
253
254 // The loop enclosing this one, or NULL if this is the outermost loop.
255 struct sLoop* enclosing;
256} Loop;
257
258// The different signature syntaxes for different kinds of methods.
259typedef enum
260{
261 // A name followed by a (possibly empty) parenthesized parameter list. Also
262 // used for binary operators.
263 SIG_METHOD,
264
265 // Just a name. Also used for unary operators.
266 SIG_GETTER,
267
268 // A name followed by "=".
269 SIG_SETTER,
270
271 // A square bracketed parameter list.
272 SIG_SUBSCRIPT,
273
274 // A square bracketed parameter list followed by "=".
275 SIG_SUBSCRIPT_SETTER,
276
277 // A constructor initializer function. This has a distinct signature to
278 // prevent it from being invoked directly outside of the constructor on the
279 // metaclass.
280 SIG_INITIALIZER
281} SignatureType;
282
283typedef struct
284{
285 const char* name;
286 int length;
287 SignatureType type;
288 int arity;
289} Signature;
290
291// Bookkeeping information for compiling a class definition.
292typedef struct
293{
294 // The name of the class.
295 ObjString* name;
296
297 // Attributes for the class itself
298 ObjMap* classAttributes;
299 // Attributes for methods in this class
300 ObjMap* methodAttributes;
301
302 // Symbol table for the fields of the class.
303 SymbolTable fields;
304
305 // Symbols for the methods defined by the class. Used to detect duplicate
306 // method definitions.
307 IntBuffer methods;
308 IntBuffer staticMethods;
309
310 // True if the class being compiled is a foreign class.
311 bool isForeign;
312
313 // True if the current method being compiled is static.
314 bool inStatic;
315
316 // The signature of the method being compiled.
317 Signature* signature;
318} ClassInfo;
319
320struct sCompiler
321{
322 Parser* parser;
323
324 // The compiler for the function enclosing this one, or NULL if it's the
325 // top level.
326 struct sCompiler* parent;
327
328 // The currently in scope local variables.
329 Local locals[MAX_LOCALS];
330
331 // The number of local variables currently in scope.
332 int numLocals;
333
334 // The upvalues that this function has captured from outer scopes. The count
335 // of them is stored in [numUpvalues].
336 CompilerUpvalue upvalues[MAX_UPVALUES];
337
338 // The current level of block scope nesting, where zero is no nesting. A -1
339 // here means top-level code is being compiled and there is no block scope
340 // in effect at all. Any variables declared will be module-level.
341 int scopeDepth;
342
343 // The current number of slots (locals and temporaries) in use.
344 //
345 // We use this and maxSlots to track the maximum number of additional slots
346 // a function may need while executing. When the function is called, the
347 // fiber will check to ensure its stack has enough room to cover that worst
348 // case and grow the stack if needed.
349 //
350 // This value here doesn't include parameters to the function. Since those
351 // are already pushed onto the stack by the caller and tracked there, we
352 // don't need to double count them here.
353 int numSlots;
354
355 // The current innermost loop being compiled, or NULL if not in a loop.
356 Loop* loop;
357
358 // If this is a compiler for a method, keeps track of the class enclosing it.
359 ClassInfo* enclosingClass;
360
361 // The function being compiled.
362 ObjFn* fn;
363
364 // The constants for the function being compiled.
365 ObjMap* constants;
366
367 // Whether or not the compiler is for a constructor initializer
368 bool isInitializer;
369
370 // The number of attributes seen while parsing.
371 // We track this separately as compile time attributes
372 // are not stored, so we can't rely on attributes->count
373 // to enforce an error message when attributes are used
374 // anywhere other than methods or classes.
375 int numAttributes;
376 // Attributes for the next class or method.
377 ObjMap* attributes;
378};
379
380// Describes where a variable is declared.
381typedef enum
382{
383 // A local variable in the current function.
384 SCOPE_LOCAL,
385
386 // A local variable declared in an enclosing function.
387 SCOPE_UPVALUE,
388
389 // A top-level module variable.
390 SCOPE_MODULE
391} Scope;
392
393// A reference to a variable and the scope where it is defined. This contains
394// enough information to emit correct code to load or store the variable.
395typedef struct
396{
397 // The stack slot, upvalue slot, or module symbol defining the variable.
398 int index;
399
400 // Where the variable is declared.
401 Scope scope;
402} Variable;
403
404// Forward declarations
405static void disallowAttributes(Compiler* compiler);
406static void addToAttributeGroup(Compiler* compiler, Value group, Value key, Value value);
407static void emitClassAttributes(Compiler* compiler, ClassInfo* classInfo);
408static void copyAttributes(Compiler* compiler, ObjMap* into);
409static void copyMethodAttributes(Compiler* compiler, bool isForeign,
410 bool isStatic, const char* fullSignature, int32_t length);
411
412// The stack effect of each opcode. The index in the array is the opcode, and
413// the value is the stack effect of that instruction.
414static const int stackEffects[] = {
415 #define OPCODE(_, effect) effect,
416 #include "wren_opcodes.h"
417 #undef OPCODE
418};
419
420static void printError(Parser* parser, int line, const char* label,
421 const char* format, va_list args)
422{
423 parser->hasError = true;
424 if (!parser->printErrors) return;
425
426 // Only report errors if there is a WrenErrorFn to handle them.
427 if (parser->vm->config.errorFn == NULL) return;
428
429 // Format the label and message.
430 char message[ERROR_MESSAGE_SIZE];
431 int length = sprintf(message, "%s: ", label);
432 length += vsprintf(message + length, format, args);
433 ASSERT(length < ERROR_MESSAGE_SIZE, "Error should not exceed buffer.");
434
435 ObjString* module = parser->module->name;
436 const char* module_name = module ? module->value : "<unknown>";
437
438 parser->vm->config.errorFn(parser->vm, WREN_ERROR_COMPILE,
439 module_name, line, message);
440}
441
442// Outputs a lexical error.
443static void lexError(Parser* parser, const char* format, ...)
444{
445 va_list args;
446 va_start(args, format);
447 printError(parser, parser->currentLine, "Error", format, args);
448 va_end(args);
449}
450
451// Outputs a compile or syntax error. This also marks the compilation as having
452// an error, which ensures that the resulting code will be discarded and never
453// run. This means that after calling error(), it's fine to generate whatever
454// invalid bytecode you want since it won't be used.
455//
456// You'll note that most places that call error() continue to parse and compile
457// after that. That's so that we can try to find as many compilation errors in
458// one pass as possible instead of just bailing at the first one.
459static void error(Compiler* compiler, const char* format, ...)
460{
461 Token* token = &compiler->parser->previous;
462
463 // If the parse error was caused by an error token, the lexer has already
464 // reported it.
465 if (token->type == TOKEN_ERROR) return;
466
467 va_list args;
468 va_start(args, format);
469 if (token->type == TOKEN_LINE)
470 {
471 printError(compiler->parser, token->line, "Error at newline", format, args);
472 }
473 else if (token->type == TOKEN_EOF)
474 {
475 printError(compiler->parser, token->line,
476 "Error at end of file", format, args);
477 }
478 else
479 {
480 // Make sure we don't exceed the buffer with a very long token.
481 char label[10 + MAX_VARIABLE_NAME + 4 + 1];
482 if (token->length <= MAX_VARIABLE_NAME)
483 {
484 sprintf(label, "Error at '%.*s'", token->length, token->start);
485 }
486 else
487 {
488 sprintf(label, "Error at '%.*s...'", MAX_VARIABLE_NAME, token->start);
489 }
490 printError(compiler->parser, token->line, label, format, args);
491 }
492 va_end(args);
493}
494
495// Adds [constant] to the constant pool and returns its index.
496static int addConstant(Compiler* compiler, Value constant)
497{
498 if (compiler->parser->hasError) return -1;
499
500 // See if we already have a constant for the value. If so, reuse it.
501 if (compiler->constants != NULL)
502 {
503 Value existing = wrenMapGet(compiler->constants, constant);
504 if (IS_NUM(existing)) return (int)AS_NUM(existing);
505 }
506
507 // It's a new constant.
508 if (compiler->fn->constants.count < MAX_CONSTANTS)
509 {
510 if (IS_OBJ(constant)) wrenPushRoot(compiler->parser->vm, AS_OBJ(constant));
511 wrenValueBufferWrite(compiler->parser->vm, &compiler->fn->constants,
512 constant);
513 if (IS_OBJ(constant)) wrenPopRoot(compiler->parser->vm);
514
515 if (compiler->constants == NULL)
516 {
517 compiler->constants = wrenNewMap(compiler->parser->vm);
518 }
519 wrenMapSet(compiler->parser->vm, compiler->constants, constant,
520 NUM_VAL(compiler->fn->constants.count - 1));
521 }
522 else
523 {
524 error(compiler, "A function may only contain %d unique constants.",
525 MAX_CONSTANTS);
526 }
527
528 return compiler->fn->constants.count - 1;
529}
530
531// Initializes [compiler].
532static void initCompiler(Compiler* compiler, Parser* parser, Compiler* parent,
533 bool isMethod)
534{
535 compiler->parser = parser;
536 compiler->parent = parent;
537 compiler->loop = NULL;
538 compiler->enclosingClass = NULL;
539 compiler->isInitializer = false;
540
541 // Initialize these to NULL before allocating in case a GC gets triggered in
542 // the middle of initializing the compiler.
543 compiler->fn = NULL;
544 compiler->constants = NULL;
545
546 parser->vm->compiler = compiler;
547
548 // Declare a local slot for either the closure or method receiver so that we
549 // don't try to reuse that slot for a user-defined local variable. For
550 // methods, we name it "this", so that we can resolve references to that like
551 // a normal variable. For functions, they have no explicit "this", so we use
552 // an empty name. That way references to "this" inside a function walks up
553 // the parent chain to find a method enclosing the function whose "this" we
554 // can close over.
555 compiler->numLocals = 1;
556 compiler->numSlots = compiler->numLocals;
557
558 if (isMethod)
559 {
560 compiler->locals[0].name = "this";
561 compiler->locals[0].length = 4;
562 }
563 else
564 {
565 compiler->locals[0].name = NULL;
566 compiler->locals[0].length = 0;
567 }
568
569 compiler->locals[0].depth = -1;
570 compiler->locals[0].isUpvalue = false;
571
572 if (parent == NULL)
573 {
574 // Compiling top-level code, so the initial scope is module-level.
575 compiler->scopeDepth = -1;
576 }
577 else
578 {
579 // The initial scope for functions and methods is local scope.
580 compiler->scopeDepth = 0;
581 }
582
583 compiler->numAttributes = 0;
584 compiler->attributes = wrenNewMap(parser->vm);
585 compiler->fn = wrenNewFunction(parser->vm, parser->module,
586 compiler->numLocals);
587}
588
589// Lexing ----------------------------------------------------------------------
590
591typedef struct
592{
593 const char* identifier;
594 size_t length;
595 TokenType tokenType;
596} Keyword;
597
598// The table of reserved words and their associated token types.
599static Keyword keywords[] =
600{
601 {"break", 5, TOKEN_BREAK},
602 {"continue", 8, TOKEN_CONTINUE},
603 {"class", 5, TOKEN_CLASS},
604 {"construct", 9, TOKEN_CONSTRUCT},
605 {"else", 4, TOKEN_ELSE},
606 {"false", 5, TOKEN_FALSE},
607 {"for", 3, TOKEN_FOR},
608 {"foreign", 7, TOKEN_FOREIGN},
609 {"if", 2, TOKEN_IF},
610 {"import", 6, TOKEN_IMPORT},
611 {"as", 2, TOKEN_AS},
612 {"in", 2, TOKEN_IN},
613 {"is", 2, TOKEN_IS},
614 {"null", 4, TOKEN_NULL},
615 {"return", 6, TOKEN_RETURN},
616 {"static", 6, TOKEN_STATIC},
617 {"super", 5, TOKEN_SUPER},
618 {"this", 4, TOKEN_THIS},
619 {"true", 4, TOKEN_TRUE},
620 {"var", 3, TOKEN_VAR},
621 {"while", 5, TOKEN_WHILE},
622 {NULL, 0, TOKEN_EOF} // Sentinel to mark the end of the array.
623};
624
625// Returns true if [c] is a valid (non-initial) identifier character.
626static bool isName(char c)
627{
628 return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_';
629}
630
631// Returns true if [c] is a digit.
632static bool isDigit(char c)
633{
634 return c >= '0' && c <= '9';
635}
636
637// Returns the current character the parser is sitting on.
638static char peekChar(Parser* parser)
639{
640 return *parser->currentChar;
641}
642
643// Returns the character after the current character.
644static char peekNextChar(Parser* parser)
645{
646 // If we're at the end of the source, don't read past it.
647 if (peekChar(parser) == '\0') return '\0';
648 return *(parser->currentChar + 1);
649}
650
651// Advances the parser forward one character.
652static char nextChar(Parser* parser)
653{
654 char c = peekChar(parser);
655 parser->currentChar++;
656 if (c == '\n') parser->currentLine++;
657 return c;
658}
659
660// If the current character is [c], consumes it and returns `true`.
661static bool matchChar(Parser* parser, char c)
662{
663 if (peekChar(parser) != c) return false;
664 nextChar(parser);
665 return true;
666}
667
668// Sets the parser's current token to the given [type] and current character
669// range.
670static void makeToken(Parser* parser, TokenType type)
671{
672 parser->next.type = type;
673 parser->next.start = parser->tokenStart;
674 parser->next.length = (int)(parser->currentChar - parser->tokenStart);
675 parser->next.line = parser->currentLine;
676
677 // Make line tokens appear on the line containing the "\n".
678 if (type == TOKEN_LINE) parser->next.line--;
679}
680
681// If the current character is [c], then consumes it and makes a token of type
682// [two]. Otherwise makes a token of type [one].
683static void twoCharToken(Parser* parser, char c, TokenType two, TokenType one)
684{
685 makeToken(parser, matchChar(parser, c) ? two : one);
686}
687
688// Skips the rest of the current line.
689static void skipLineComment(Parser* parser)
690{
691 while (peekChar(parser) != '\n' && peekChar(parser) != '\0')
692 {
693 nextChar(parser);
694 }
695}
696
697// Skips the rest of a block comment.
698static void skipBlockComment(Parser* parser)
699{
700 int nesting = 1;
701 while (nesting > 0)
702 {
703 if (peekChar(parser) == '\0')
704 {
705 lexError(parser, "Unterminated block comment.");
706 return;
707 }
708
709 if (peekChar(parser) == '/' && peekNextChar(parser) == '*')
710 {
711 nextChar(parser);
712 nextChar(parser);
713 nesting++;
714 continue;
715 }
716
717 if (peekChar(parser) == '*' && peekNextChar(parser) == '/')
718 {
719 nextChar(parser);
720 nextChar(parser);
721 nesting--;
722 continue;
723 }
724
725 // Regular comment character.
726 nextChar(parser);
727 }
728}
729
730// Reads the next character, which should be a hex digit (0-9, a-f, or A-F) and
731// returns its numeric value. If the character isn't a hex digit, returns -1.
732static int readHexDigit(Parser* parser)
733{
734 char c = nextChar(parser);
735 if (c >= '0' && c <= '9') return c - '0';
736 if (c >= 'a' && c <= 'f') return c - 'a' + 10;
737 if (c >= 'A' && c <= 'F') return c - 'A' + 10;
738
739 // Don't consume it if it isn't expected. Keeps us from reading past the end
740 // of an unterminated string.
741 parser->currentChar--;
742 return -1;
743}
744
745// Parses the numeric value of the current token.
746static void makeNumber(Parser* parser, bool isHex)
747{
748 errno = 0;
749
750 if (isHex)
751 {
752 parser->next.value = NUM_VAL((double)strtoll(parser->tokenStart, NULL, 16));
753 }
754 else
755 {
756 parser->next.value = NUM_VAL(strtod(parser->tokenStart, NULL));
757 }
758
759 if (errno == ERANGE)
760 {
761 lexError(parser, "Number literal was too large (%d).", sizeof(long int));
762 parser->next.value = NUM_VAL(0);
763 }
764
765 // We don't check that the entire token is consumed after calling strtoll()
766 // or strtod() because we've already scanned it ourselves and know it's valid.
767
768 makeToken(parser, TOKEN_NUMBER);
769}
770
771// Finishes lexing a hexadecimal number literal.
772static void readHexNumber(Parser* parser)
773{
774 // Skip past the `x` used to denote a hexadecimal literal.
775 nextChar(parser);
776
777 // Iterate over all the valid hexadecimal digits found.
778 while (readHexDigit(parser) != -1) continue;
779
780 makeNumber(parser, true);
781}
782
783// Finishes lexing a number literal.
784static void readNumber(Parser* parser)
785{
786 while (isDigit(peekChar(parser))) nextChar(parser);
787
788 // See if it has a floating point. Make sure there is a digit after the "."
789 // so we don't get confused by method calls on number literals.
790 if (peekChar(parser) == '.' && isDigit(peekNextChar(parser)))
791 {
792 nextChar(parser);
793 while (isDigit(peekChar(parser))) nextChar(parser);
794 }
795
796 // See if the number is in scientific notation.
797 if (matchChar(parser, 'e') || matchChar(parser, 'E'))
798 {
799 // Allow a single positive/negative exponent symbol.
800 if(!matchChar(parser, '+'))
801 {
802 matchChar(parser, '-');
803 }
804
805 if (!isDigit(peekChar(parser)))
806 {
807 lexError(parser, "Unterminated scientific notation.");
808 }
809
810 while (isDigit(peekChar(parser))) nextChar(parser);
811 }
812
813 makeNumber(parser, false);
814}
815
816// Finishes lexing an identifier. Handles reserved words.
817static void readName(Parser* parser, TokenType type, char firstChar)
818{
819 ByteBuffer string;
820 wrenByteBufferInit(&string);
821 wrenByteBufferWrite(parser->vm, &string, firstChar);
822
823 while (isName(peekChar(parser)) || isDigit(peekChar(parser)))
824 {
825 char c = nextChar(parser);
826 wrenByteBufferWrite(parser->vm, &string, c);
827 }
828
829 // Update the type if it's a keyword.
830 size_t length = parser->currentChar - parser->tokenStart;
831 for (int i = 0; keywords[i].identifier != NULL; i++)
832 {
833 if (length == keywords[i].length &&
834 memcmp(parser->tokenStart, keywords[i].identifier, length) == 0)
835 {
836 type = keywords[i].tokenType;
837 break;
838 }
839 }
840
841 parser->next.value = wrenNewStringLength(parser->vm,
842 (char*)string.data, string.count);
843
844 wrenByteBufferClear(parser->vm, &string);
845 makeToken(parser, type);
846}
847
848// Reads [digits] hex digits in a string literal and returns their number value.
849static int readHexEscape(Parser* parser, int digits, const char* description)
850{
851 int value = 0;
852 for (int i = 0; i < digits; i++)
853 {
854 if (peekChar(parser) == '"' || peekChar(parser) == '\0')
855 {
856 lexError(parser, "Incomplete %s escape sequence.", description);
857
858 // Don't consume it if it isn't expected. Keeps us from reading past the
859 // end of an unterminated string.
860 parser->currentChar--;
861 break;
862 }
863
864 int digit = readHexDigit(parser);
865 if (digit == -1)
866 {
867 lexError(parser, "Invalid %s escape sequence.", description);
868 break;
869 }
870
871 value = (value * 16) | digit;
872 }
873
874 return value;
875}
876
877// Reads a hex digit Unicode escape sequence in a string literal.
878static void readUnicodeEscape(Parser* parser, ByteBuffer* string, int length)
879{
880 int value = readHexEscape(parser, length, "Unicode");
881
882 // Grow the buffer enough for the encoded result.
883 int numBytes = wrenUtf8EncodeNumBytes(value);
884 if (numBytes != 0)
885 {
886 wrenByteBufferFill(parser->vm, string, 0, numBytes);
887 wrenUtf8Encode(value, string->data + string->count - numBytes);
888 }
889}
890
891static void readRawString(Parser* parser)
892{
893 ByteBuffer string;
894 wrenByteBufferInit(&string);
895 TokenType type = TOKEN_STRING;
896
897 //consume the second and third "
898 nextChar(parser);
899 nextChar(parser);
900
901 int skipStart = 0;
902 int firstNewline = -1;
903
904 int skipEnd = -1;
905 int lastNewline = -1;
906
907 for (;;)
908 {
909 char c = nextChar(parser);
910 char c1 = peekChar(parser);
911 char c2 = peekNextChar(parser);
912
913 if(c == '\n') {
914 lastNewline = string.count;
915 skipEnd = lastNewline;
916 firstNewline = firstNewline == -1 ? string.count : firstNewline;
917 }
918
919 if(c == '"' && c1 == '"' && c2 == '"') break;
920
921 bool isWhitespace = c == ' ' || c == '\t';
922 skipEnd = c == '\n' || isWhitespace ? skipEnd : -1;
923
924 // If we haven't seen a newline or other character yet,
925 // and still seeing whitespace, count the characters
926 // as skippable till we know otherwise
927 bool skippable = skipStart != -1 && isWhitespace && firstNewline == -1;
928 skipStart = skippable ? string.count + 1 : skipStart;
929
930 // We've counted leading whitespace till we hit something else,
931 // but it's not a newline, so we reset skipStart since we need these characters
932 if (firstNewline == -1 && !isWhitespace && c != '\n') skipStart = -1;
933
934 if (c == '\0' || c1 == '\0' || c2 == '\0')
935 {
936 lexError(parser, "Unterminated raw string.");
937
938 // Don't consume it if it isn't expected. Keeps us from reading past the
939 // end of an unterminated string.
940 parser->currentChar--;
941 break;
942 }
943
944 wrenByteBufferWrite(parser->vm, &string, c);
945 }
946
947 //consume the second and third "
948 nextChar(parser);
949 nextChar(parser);
950
951 int offset = 0;
952 int count = string.count;
953
954 if(firstNewline != -1 && skipStart == firstNewline) offset = firstNewline + 1;
955 if(lastNewline != -1 && skipEnd == lastNewline) count = lastNewline;
956
957 count -= (offset > count) ? count : offset;
958
959 parser->next.value = wrenNewStringLength(parser->vm,
960 ((char*)string.data) + offset, count);
961
962 wrenByteBufferClear(parser->vm, &string);
963 makeToken(parser, type);
964}
965
966// Finishes lexing a string literal.
967static void readString(Parser* parser)
968{
969 ByteBuffer string;
970 TokenType type = TOKEN_STRING;
971 wrenByteBufferInit(&string);
972
973 for (;;)
974 {
975 char c = nextChar(parser);
976 if (c == '"') break;
977
978 if (c == '\0')
979 {
980 lexError(parser, "Unterminated string.");
981
982 // Don't consume it if it isn't expected. Keeps us from reading past the
983 // end of an unterminated string.
984 parser->currentChar--;
985 break;
986 }
987
988 if (c == '%')
989 {
990 if (parser->numParens < MAX_INTERPOLATION_NESTING)
991 {
992 // TODO: Allow format string.
993 if (nextChar(parser) != '(') lexError(parser, "Expect '(' after '%%'.");
994
995 parser->parens[parser->numParens++] = 1;
996 type = TOKEN_INTERPOLATION;
997 break;
998 }
999
1000 lexError(parser, "Interpolation may only nest %d levels deep.",
1001 MAX_INTERPOLATION_NESTING);
1002 }
1003
1004 if (c == '\\')
1005 {
1006 switch (nextChar(parser))
1007 {
1008 case '"': wrenByteBufferWrite(parser->vm, &string, '"'); break;
1009 case '\\': wrenByteBufferWrite(parser->vm, &string, '\\'); break;
1010 case '%': wrenByteBufferWrite(parser->vm, &string, '%'); break;
1011 case '0': wrenByteBufferWrite(parser->vm, &string, '\0'); break;
1012 case 'a': wrenByteBufferWrite(parser->vm, &string, '\a'); break;
1013 case 'b': wrenByteBufferWrite(parser->vm, &string, '\b'); break;
1014 case 'e': wrenByteBufferWrite(parser->vm, &string, '\33'); break;
1015 case 'f': wrenByteBufferWrite(parser->vm, &string, '\f'); break;
1016 case 'n': wrenByteBufferWrite(parser->vm, &string, '\n'); break;
1017 case 'r': wrenByteBufferWrite(parser->vm, &string, '\r'); break;
1018 case 't': wrenByteBufferWrite(parser->vm, &string, '\t'); break;
1019 case 'u': readUnicodeEscape(parser, &string, 4); break;
1020 case 'U': readUnicodeEscape(parser, &string, 8); break;
1021 case 'v': wrenByteBufferWrite(parser->vm, &string, '\v'); break;
1022 case 'x':
1023 wrenByteBufferWrite(parser->vm, &string,
1024 (uint8_t)readHexEscape(parser, 2, "byte"));
1025 break;
1026
1027 default:
1028 lexError(parser, "Invalid escape character '%c'.",
1029 *(parser->currentChar - 1));
1030 break;
1031 }
1032 }
1033 else
1034 {
1035 wrenByteBufferWrite(parser->vm, &string, c);
1036 }
1037 }
1038
1039 parser->next.value = wrenNewStringLength(parser->vm,
1040 (char*)string.data, string.count);
1041
1042 wrenByteBufferClear(parser->vm, &string);
1043 makeToken(parser, type);
1044}
1045
1046// Lex the next token and store it in [parser.next].
1047static void nextToken(Parser* parser)
1048{
1049 parser->previous = parser->current;
1050 parser->current = parser->next;
1051
1052 // If we are out of tokens, don't try to tokenize any more. We *do* still
1053 // copy the TOKEN_EOF to previous so that code that expects it to be consumed
1054 // will still work.
1055 if (parser->next.type == TOKEN_EOF) return;
1056 if (parser->current.type == TOKEN_EOF) return;
1057
1058 while (peekChar(parser) != '\0')
1059 {
1060 parser->tokenStart = parser->currentChar;
1061
1062 char c = nextChar(parser);
1063 switch (c)
1064 {
1065 case '(':
1066 // If we are inside an interpolated expression, count the unmatched "(".
1067 if (parser->numParens > 0) parser->parens[parser->numParens - 1]++;
1068 makeToken(parser, TOKEN_LEFT_PAREN);
1069 return;
1070
1071 case ')':
1072 // If we are inside an interpolated expression, count the ")".
1073 if (parser->numParens > 0 &&
1074 --parser->parens[parser->numParens - 1] == 0)
1075 {
1076 // This is the final ")", so the interpolation expression has ended.
1077 // This ")" now begins the next section of the template string.
1078 parser->numParens--;
1079 readString(parser);
1080 return;
1081 }
1082
1083 makeToken(parser, TOKEN_RIGHT_PAREN);
1084 return;
1085
1086 case '[': makeToken(parser, TOKEN_LEFT_BRACKET); return;
1087 case ']': makeToken(parser, TOKEN_RIGHT_BRACKET); return;
1088 case '{': makeToken(parser, TOKEN_LEFT_BRACE); return;
1089 case '}': makeToken(parser, TOKEN_RIGHT_BRACE); return;
1090 case ':': makeToken(parser, TOKEN_COLON); return;
1091 case ',': makeToken(parser, TOKEN_COMMA); return;
1092 case '*': makeToken(parser, TOKEN_STAR); return;
1093 case '%': makeToken(parser, TOKEN_PERCENT); return;
1094 case '#': {
1095 // Ignore shebang on the first line.
1096 if (parser->currentLine == 1 && peekChar(parser) == '!' && peekNextChar(parser) == '/')
1097 {
1098 skipLineComment(parser);
1099 break;
1100 }
1101 // Otherwise we treat it as a token a token
1102 makeToken(parser, TOKEN_HASH);
1103 return;
1104 }
1105 case '^': makeToken(parser, TOKEN_CARET); return;
1106 case '+': makeToken(parser, TOKEN_PLUS); return;
1107 case '-': makeToken(parser, TOKEN_MINUS); return;
1108 case '~': makeToken(parser, TOKEN_TILDE); return;
1109 case '?': makeToken(parser, TOKEN_QUESTION); return;
1110
1111 case '|': twoCharToken(parser, '|', TOKEN_PIPEPIPE, TOKEN_PIPE); return;
1112 case '&': twoCharToken(parser, '&', TOKEN_AMPAMP, TOKEN_AMP); return;
1113 case '=': twoCharToken(parser, '=', TOKEN_EQEQ, TOKEN_EQ); return;
1114 case '!': twoCharToken(parser, '=', TOKEN_BANGEQ, TOKEN_BANG); return;
1115
1116 case '.':
1117 if (matchChar(parser, '.'))
1118 {
1119 twoCharToken(parser, '.', TOKEN_DOTDOTDOT, TOKEN_DOTDOT);
1120 return;
1121 }
1122
1123 makeToken(parser, TOKEN_DOT);
1124 return;
1125
1126 case '/':
1127 if (matchChar(parser, '/'))
1128 {
1129 skipLineComment(parser);
1130 break;
1131 }
1132
1133 if (matchChar(parser, '*'))
1134 {
1135 skipBlockComment(parser);
1136 break;
1137 }
1138
1139 makeToken(parser, TOKEN_SLASH);
1140 return;
1141
1142 case '<':
1143 if (matchChar(parser, '<'))
1144 {
1145 makeToken(parser, TOKEN_LTLT);
1146 }
1147 else
1148 {
1149 twoCharToken(parser, '=', TOKEN_LTEQ, TOKEN_LT);
1150 }
1151 return;
1152
1153 case '>':
1154 if (matchChar(parser, '>'))
1155 {
1156 makeToken(parser, TOKEN_GTGT);
1157 }
1158 else
1159 {
1160 twoCharToken(parser, '=', TOKEN_GTEQ, TOKEN_GT);
1161 }
1162 return;
1163
1164 case '\n':
1165 makeToken(parser, TOKEN_LINE);
1166 return;
1167
1168 case ' ':
1169 case '\r':
1170 case '\t':
1171 // Skip forward until we run out of whitespace.
1172 while (peekChar(parser) == ' ' ||
1173 peekChar(parser) == '\r' ||
1174 peekChar(parser) == '\t')
1175 {
1176 nextChar(parser);
1177 }
1178 break;
1179
1180 case '"': {
1181 if(peekChar(parser) == '"' && peekNextChar(parser) == '"') {
1182 readRawString(parser);
1183 return;
1184 }
1185 readString(parser); return;
1186 }
1187 case '_':
1188 readName(parser,
1189 peekChar(parser) == '_' ? TOKEN_STATIC_FIELD : TOKEN_FIELD, c);
1190 return;
1191
1192 case '0':
1193 if (peekChar(parser) == 'x')
1194 {
1195 readHexNumber(parser);
1196 return;
1197 }
1198
1199 readNumber(parser);
1200 return;
1201
1202 default:
1203 if (isName(c))
1204 {
1205 readName(parser, TOKEN_NAME, c);
1206 }
1207 else if (isDigit(c))
1208 {
1209 readNumber(parser);
1210 }
1211 else
1212 {
1213 if (c >= 32 && c <= 126)
1214 {
1215 lexError(parser, "Invalid character '%c'.", c);
1216 }
1217 else
1218 {
1219 // Don't show non-ASCII values since we didn't UTF-8 decode the
1220 // bytes. Since there are no non-ASCII byte values that are
1221 // meaningful code units in Wren, the lexer works on raw bytes,
1222 // even though the source code and console output are UTF-8.
1223 lexError(parser, "Invalid byte 0x%x.", (uint8_t)c);
1224 }
1225 parser->next.type = TOKEN_ERROR;
1226 parser->next.length = 0;
1227 }
1228 return;
1229 }
1230 }
1231
1232 // If we get here, we're out of source, so just make EOF tokens.
1233 parser->tokenStart = parser->currentChar;
1234 makeToken(parser, TOKEN_EOF);
1235}
1236
1237// Parsing ---------------------------------------------------------------------
1238
1239// Returns the type of the current token.
1240static TokenType peek(Compiler* compiler)
1241{
1242 return compiler->parser->current.type;
1243}
1244
1245// Returns the type of the current token.
1246static TokenType peekNext(Compiler* compiler)
1247{
1248 return compiler->parser->next.type;
1249}
1250
1251// Consumes the current token if its type is [expected]. Returns true if a
1252// token was consumed.
1253static bool match(Compiler* compiler, TokenType expected)
1254{
1255 if (peek(compiler) != expected) return false;
1256
1257 nextToken(compiler->parser);
1258 return true;
1259}
1260
1261// Consumes the current token. Emits an error if its type is not [expected].
1262static void consume(Compiler* compiler, TokenType expected,
1263 const char* errorMessage)
1264{
1265 nextToken(compiler->parser);
1266 if (compiler->parser->previous.type != expected)
1267 {
1268 error(compiler, errorMessage);
1269
1270 // If the next token is the one we want, assume the current one is just a
1271 // spurious error and discard it to minimize the number of cascaded errors.
1272 if (compiler->parser->current.type == expected) nextToken(compiler->parser);
1273 }
1274}
1275
1276// Matches one or more newlines. Returns true if at least one was found.
1277static bool matchLine(Compiler* compiler)
1278{
1279 if (!match(compiler, TOKEN_LINE)) return false;
1280
1281 while (match(compiler, TOKEN_LINE));
1282 return true;
1283}
1284
1285// Discards any newlines starting at the current token.
1286static void ignoreNewlines(Compiler* compiler)
1287{
1288 matchLine(compiler);
1289}
1290
1291// Consumes the current token. Emits an error if it is not a newline. Then
1292// discards any duplicate newlines following it.
1293static void consumeLine(Compiler* compiler, const char* errorMessage)
1294{
1295 consume(compiler, TOKEN_LINE, errorMessage);
1296 ignoreNewlines(compiler);
1297}
1298
1299static void allowLineBeforeDot(Compiler* compiler) {
1300 if (peek(compiler) == TOKEN_LINE && peekNext(compiler) == TOKEN_DOT) {
1301 nextToken(compiler->parser);
1302 }
1303}
1304
1305// Variables and scopes --------------------------------------------------------
1306
1307// Emits one single-byte argument. Returns its index.
1308static int emitByte(Compiler* compiler, int byte)
1309{
1310 wrenByteBufferWrite(compiler->parser->vm, &compiler->fn->code, (uint8_t)byte);
1311
1312 // Assume the instruction is associated with the most recently consumed token.
1313 wrenIntBufferWrite(compiler->parser->vm, &compiler->fn->debug->sourceLines,
1314 compiler->parser->previous.line);
1315
1316 return compiler->fn->code.count - 1;
1317}
1318
1319// Emits one bytecode instruction.
1320static void emitOp(Compiler* compiler, Code instruction)
1321{
1322 emitByte(compiler, instruction);
1323
1324 // Keep track of the stack's high water mark.
1325 compiler->numSlots += stackEffects[instruction];
1326 if (compiler->numSlots > compiler->fn->maxSlots)
1327 {
1328 compiler->fn->maxSlots = compiler->numSlots;
1329 }
1330}
1331
1332// Emits one 16-bit argument, which will be written big endian.
1333static void emitShort(Compiler* compiler, int arg)
1334{
1335 emitByte(compiler, (arg >> 8) & 0xff);
1336 emitByte(compiler, arg & 0xff);
1337}
1338
1339// Emits one bytecode instruction followed by a 8-bit argument. Returns the
1340// index of the argument in the bytecode.
1341static int emitByteArg(Compiler* compiler, Code instruction, int arg)
1342{
1343 emitOp(compiler, instruction);
1344 return emitByte(compiler, arg);
1345}
1346
1347// Emits one bytecode instruction followed by a 16-bit argument, which will be
1348// written big endian.
1349static void emitShortArg(Compiler* compiler, Code instruction, int arg)
1350{
1351 emitOp(compiler, instruction);
1352 emitShort(compiler, arg);
1353}
1354
1355// Emits [instruction] followed by a placeholder for a jump offset. The
1356// placeholder can be patched by calling [jumpPatch]. Returns the index of the
1357// placeholder.
1358static int emitJump(Compiler* compiler, Code instruction)
1359{
1360 emitOp(compiler, instruction);
1361 emitByte(compiler, 0xff);
1362 return emitByte(compiler, 0xff) - 1;
1363}
1364
1365// Creates a new constant for the current value and emits the bytecode to load
1366// it from the constant table.
1367static void emitConstant(Compiler* compiler, Value value)
1368{
1369 int constant = addConstant(compiler, value);
1370
1371 // Compile the code to load the constant.
1372 emitShortArg(compiler, CODE_CONSTANT, constant);
1373}
1374
1375// Create a new local variable with [name]. Assumes the current scope is local
1376// and the name is unique.
1377static int addLocal(Compiler* compiler, const char* name, int length)
1378{
1379 Local* local = &compiler->locals[compiler->numLocals];
1380 local->name = name;
1381 local->length = length;
1382 local->depth = compiler->scopeDepth;
1383 local->isUpvalue = false;
1384 return compiler->numLocals++;
1385}
1386
1387// Declares a variable in the current scope whose name is the given token.
1388//
1389// If [token] is `NULL`, uses the previously consumed token. Returns its symbol.
1390static int declareVariable(Compiler* compiler, Token* token)
1391{
1392 if (token == NULL) token = &compiler->parser->previous;
1393
1394 if (token->length > MAX_VARIABLE_NAME)
1395 {
1396 error(compiler, "Variable name cannot be longer than %d characters.",
1397 MAX_VARIABLE_NAME);
1398 }
1399
1400 // Top-level module scope.
1401 if (compiler->scopeDepth == -1)
1402 {
1403 int line = -1;
1404 int symbol = wrenDefineVariable(compiler->parser->vm,
1405 compiler->parser->module,
1406 token->start, token->length,
1407 NULL_VAL, &line);
1408
1409 if (symbol == -1)
1410 {
1411 error(compiler, "Module variable is already defined.");
1412 }
1413 else if (symbol == -2)
1414 {
1415 error(compiler, "Too many module variables defined.");
1416 }
1417 else if (symbol == -3)
1418 {
1419 error(compiler,
1420 "Variable '%.*s' referenced before this definition (first use at line %d).",
1421 token->length, token->start, line);
1422 }
1423
1424 return symbol;
1425 }
1426
1427 // See if there is already a variable with this name declared in the current
1428 // scope. (Outer scopes are OK: those get shadowed.)
1429 for (int i = compiler->numLocals - 1; i >= 0; i--)
1430 {
1431 Local* local = &compiler->locals[i];
1432
1433 // Once we escape this scope and hit an outer one, we can stop.
1434 if (local->depth < compiler->scopeDepth) break;
1435
1436 if (local->length == token->length &&
1437 memcmp(local->name, token->start, token->length) == 0)
1438 {
1439 error(compiler, "Variable is already declared in this scope.");
1440 return i;
1441 }
1442 }
1443
1444 if (compiler->numLocals == MAX_LOCALS)
1445 {
1446 error(compiler, "Cannot declare more than %d variables in one scope.",
1447 MAX_LOCALS);
1448 return -1;
1449 }
1450
1451 return addLocal(compiler, token->start, token->length);
1452}
1453
1454// Parses a name token and declares a variable in the current scope with that
1455// name. Returns its slot.
1456static int declareNamedVariable(Compiler* compiler)
1457{
1458 consume(compiler, TOKEN_NAME, "Expect variable name.");
1459 return declareVariable(compiler, NULL);
1460}
1461
1462// Stores a variable with the previously defined symbol in the current scope.
1463static void defineVariable(Compiler* compiler, int symbol)
1464{
1465 // Store the variable. If it's a local, the result of the initializer is
1466 // in the correct slot on the stack already so we're done.
1467 if (compiler->scopeDepth >= 0) return;
1468
1469 // It's a module-level variable, so store the value in the module slot and
1470 // then discard the temporary for the initializer.
1471 emitShortArg(compiler, CODE_STORE_MODULE_VAR, symbol);
1472 emitOp(compiler, CODE_POP);
1473}
1474
1475// Starts a new local block scope.
1476static void pushScope(Compiler* compiler)
1477{
1478 compiler->scopeDepth++;
1479}
1480
1481// Generates code to discard local variables at [depth] or greater. Does *not*
1482// actually undeclare variables or pop any scopes, though. This is called
1483// directly when compiling "break" statements to ditch the local variables
1484// before jumping out of the loop even though they are still in scope *past*
1485// the break instruction.
1486//
1487// Returns the number of local variables that were eliminated.
1488static int discardLocals(Compiler* compiler, int depth)
1489{
1490 ASSERT(compiler->scopeDepth > -1, "Cannot exit top-level scope.");
1491
1492 int local = compiler->numLocals - 1;
1493 while (local >= 0 && compiler->locals[local].depth >= depth)
1494 {
1495 // If the local was closed over, make sure the upvalue gets closed when it
1496 // goes out of scope on the stack. We use emitByte() and not emitOp() here
1497 // because we don't want to track that stack effect of these pops since the
1498 // variables are still in scope after the break.
1499 if (compiler->locals[local].isUpvalue)
1500 {
1501 emitByte(compiler, CODE_CLOSE_UPVALUE);
1502 }
1503 else
1504 {
1505 emitByte(compiler, CODE_POP);
1506 }
1507
1508
1509 local--;
1510 }
1511
1512 return compiler->numLocals - local - 1;
1513}
1514
1515// Closes the last pushed block scope and discards any local variables declared
1516// in that scope. This should only be called in a statement context where no
1517// temporaries are still on the stack.
1518static void popScope(Compiler* compiler)
1519{
1520 int popped = discardLocals(compiler, compiler->scopeDepth);
1521 compiler->numLocals -= popped;
1522 compiler->numSlots -= popped;
1523 compiler->scopeDepth--;
1524}
1525
1526// Attempts to look up the name in the local variables of [compiler]. If found,
1527// returns its index, otherwise returns -1.
1528static int resolveLocal(Compiler* compiler, const char* name, int length)
1529{
1530 // Look it up in the local scopes. Look in reverse order so that the most
1531 // nested variable is found first and shadows outer ones.
1532 for (int i = compiler->numLocals - 1; i >= 0; i--)
1533 {
1534 if (compiler->locals[i].length == length &&
1535 memcmp(name, compiler->locals[i].name, length) == 0)
1536 {
1537 return i;
1538 }
1539 }
1540
1541 return -1;
1542}
1543
1544// Adds an upvalue to [compiler]'s function with the given properties. Does not
1545// add one if an upvalue for that variable is already in the list. Returns the
1546// index of the upvalue.
1547static int addUpvalue(Compiler* compiler, bool isLocal, int index)
1548{
1549 // Look for an existing one.
1550 for (int i = 0; i < compiler->fn->numUpvalues; i++)
1551 {
1552 CompilerUpvalue* upvalue = &compiler->upvalues[i];
1553 if (upvalue->index == index && upvalue->isLocal == isLocal) return i;
1554 }
1555
1556 // If we got here, it's a new upvalue.
1557 compiler->upvalues[compiler->fn->numUpvalues].isLocal = isLocal;
1558 compiler->upvalues[compiler->fn->numUpvalues].index = index;
1559 return compiler->fn->numUpvalues++;
1560}
1561
1562// Attempts to look up [name] in the functions enclosing the one being compiled
1563// by [compiler]. If found, it adds an upvalue for it to this compiler's list
1564// of upvalues (unless it's already in there) and returns its index. If not
1565// found, returns -1.
1566//
1567// If the name is found outside of the immediately enclosing function, this
1568// will flatten the closure and add upvalues to all of the intermediate
1569// functions so that it gets walked down to this one.
1570//
1571// If it reaches a method boundary, this stops and returns -1 since methods do
1572// not close over local variables.
1573static int findUpvalue(Compiler* compiler, const char* name, int length)
1574{
1575 // If we are at the top level, we didn't find it.
1576 if (compiler->parent == NULL) return -1;
1577
1578 // If we hit the method boundary (and the name isn't a static field), then
1579 // stop looking for it. We'll instead treat it as a self send.
1580 if (name[0] != '_' && compiler->parent->enclosingClass != NULL) return -1;
1581
1582 // See if it's a local variable in the immediately enclosing function.
1583 int local = resolveLocal(compiler->parent, name, length);
1584 if (local != -1)
1585 {
1586 // Mark the local as an upvalue so we know to close it when it goes out of
1587 // scope.
1588 compiler->parent->locals[local].isUpvalue = true;
1589
1590 return addUpvalue(compiler, true, local);
1591 }
1592
1593 // See if it's an upvalue in the immediately enclosing function. In other
1594 // words, if it's a local variable in a non-immediately enclosing function.
1595 // This "flattens" closures automatically: it adds upvalues to all of the
1596 // intermediate functions to get from the function where a local is declared
1597 // all the way into the possibly deeply nested function that is closing over
1598 // it.
1599 int upvalue = findUpvalue(compiler->parent, name, length);
1600 if (upvalue != -1)
1601 {
1602 return addUpvalue(compiler, false, upvalue);
1603 }
1604
1605 // If we got here, we walked all the way up the parent chain and couldn't
1606 // find it.
1607 return -1;
1608}
1609
1610// Look up [name] in the current scope to see what variable it refers to.
1611// Returns the variable either in local scope, or the enclosing function's
1612// upvalue list. Does not search the module scope. Returns a variable with
1613// index -1 if not found.
1614static Variable resolveNonmodule(Compiler* compiler,
1615 const char* name, int length)
1616{
1617 // Look it up in the local scopes.
1618 Variable variable;
1619 variable.scope = SCOPE_LOCAL;
1620 variable.index = resolveLocal(compiler, name, length);
1621 if (variable.index != -1) return variable;
1622
1623 // Tt's not a local, so guess that it's an upvalue.
1624 variable.scope = SCOPE_UPVALUE;
1625 variable.index = findUpvalue(compiler, name, length);
1626 return variable;
1627}
1628
1629// Look up [name] in the current scope to see what variable it refers to.
1630// Returns the variable either in module scope, local scope, or the enclosing
1631// function's upvalue list. Returns a variable with index -1 if not found.
1632static Variable resolveName(Compiler* compiler, const char* name, int length)
1633{
1634 Variable variable = resolveNonmodule(compiler, name, length);
1635 if (variable.index != -1) return variable;
1636
1637 variable.scope = SCOPE_MODULE;
1638 variable.index = wrenSymbolTableFind(&compiler->parser->module->variableNames,
1639 name, length);
1640 return variable;
1641}
1642
1643static void loadLocal(Compiler* compiler, int slot)
1644{
1645 if (slot <= 8)
1646 {
1647 emitOp(compiler, (Code)(CODE_LOAD_LOCAL_0 + slot));
1648 return;
1649 }
1650
1651 emitByteArg(compiler, CODE_LOAD_LOCAL, slot);
1652}
1653
1654// Finishes [compiler], which is compiling a function, method, or chunk of top
1655// level code. If there is a parent compiler, then this emits code in the
1656// parent compiler to load the resulting function.
1657static ObjFn* endCompiler(Compiler* compiler,
1658 const char* debugName, int debugNameLength)
1659{
1660 // If we hit an error, don't finish the function since it's borked anyway.
1661 if (compiler->parser->hasError)
1662 {
1663 compiler->parser->vm->compiler = compiler->parent;
1664 return NULL;
1665 }
1666
1667 // Mark the end of the bytecode. Since it may contain multiple early returns,
1668 // we can't rely on CODE_RETURN to tell us we're at the end.
1669 emitOp(compiler, CODE_END);
1670
1671 wrenFunctionBindName(compiler->parser->vm, compiler->fn,
1672 debugName, debugNameLength);
1673
1674 // In the function that contains this one, load the resulting function object.
1675 if (compiler->parent != NULL)
1676 {
1677 int constant = addConstant(compiler->parent, OBJ_VAL(compiler->fn));
1678
1679 // Wrap the function in a closure. We do this even if it has no upvalues so
1680 // that the VM can uniformly assume all called objects are closures. This
1681 // makes creating a function a little slower, but makes invoking them
1682 // faster. Given that functions are invoked more often than they are
1683 // created, this is a win.
1684 emitShortArg(compiler->parent, CODE_CLOSURE, constant);
1685
1686 // Emit arguments for each upvalue to know whether to capture a local or
1687 // an upvalue.
1688 for (int i = 0; i < compiler->fn->numUpvalues; i++)
1689 {
1690 emitByte(compiler->parent, compiler->upvalues[i].isLocal ? 1 : 0);
1691 emitByte(compiler->parent, compiler->upvalues[i].index);
1692 }
1693 }
1694
1695 // Pop this compiler off the stack.
1696 compiler->parser->vm->compiler = compiler->parent;
1697
1698 #if WREN_DEBUG_DUMP_COMPILED_CODE
1699 wrenDumpCode(compiler->parser->vm, compiler->fn);
1700 #endif
1701
1702 return compiler->fn;
1703}
1704
1705// Grammar ---------------------------------------------------------------------
1706
1707typedef enum
1708{
1709 PREC_NONE,
1710 PREC_LOWEST,
1711 PREC_ASSIGNMENT, // =
1712 PREC_CONDITIONAL, // ?:
1713 PREC_LOGICAL_OR, // ||
1714 PREC_LOGICAL_AND, // &&
1715 PREC_EQUALITY, // == !=
1716 PREC_IS, // is
1717 PREC_COMPARISON, // < > <= >=
1718 PREC_BITWISE_OR, // |
1719 PREC_BITWISE_XOR, // ^
1720 PREC_BITWISE_AND, // &
1721 PREC_BITWISE_SHIFT, // << >>
1722 PREC_RANGE, // .. ...
1723 PREC_TERM, // + -
1724 PREC_FACTOR, // * / %
1725 PREC_UNARY, // unary - ! ~
1726 PREC_CALL, // . () []
1727 PREC_PRIMARY
1728} Precedence;
1729
1730typedef void (*GrammarFn)(Compiler*, bool canAssign);
1731
1732typedef void (*SignatureFn)(Compiler* compiler, Signature* signature);
1733
1734typedef struct
1735{
1736 GrammarFn prefix;
1737 GrammarFn infix;
1738 SignatureFn method;
1739 Precedence precedence;
1740 const char* name;
1741} GrammarRule;
1742
1743// Forward declarations since the grammar is recursive.
1744static GrammarRule* getRule(TokenType type);
1745static void expression(Compiler* compiler);
1746static void statement(Compiler* compiler);
1747static void definition(Compiler* compiler);
1748static void parsePrecedence(Compiler* compiler, Precedence precedence);
1749
1750// Replaces the placeholder argument for a previous CODE_JUMP or CODE_JUMP_IF
1751// instruction with an offset that jumps to the current end of bytecode.
1752static void patchJump(Compiler* compiler, int offset)
1753{
1754 // -2 to adjust for the bytecode for the jump offset itself.
1755 int jump = compiler->fn->code.count - offset - 2;
1756 if (jump > MAX_JUMP) error(compiler, "Too much code to jump over.");
1757
1758 compiler->fn->code.data[offset] = (jump >> 8) & 0xff;
1759 compiler->fn->code.data[offset + 1] = jump & 0xff;
1760}
1761
1762// Parses a block body, after the initial "{" has been consumed.
1763//
1764// Returns true if it was a expression body, false if it was a statement body.
1765// (More precisely, returns true if a value was left on the stack. An empty
1766// block returns false.)
1767static bool finishBlock(Compiler* compiler)
1768{
1769 // Empty blocks do nothing.
1770 if (match(compiler, TOKEN_RIGHT_BRACE)) return false;
1771
1772 // If there's no line after the "{", it's a single-expression body.
1773 if (!matchLine(compiler))
1774 {
1775 expression(compiler);
1776 consume(compiler, TOKEN_RIGHT_BRACE, "Expect '}' at end of block.");
1777 return true;
1778 }
1779
1780 // Empty blocks (with just a newline inside) do nothing.
1781 if (match(compiler, TOKEN_RIGHT_BRACE)) return false;
1782
1783 // Compile the definition list.
1784 do
1785 {
1786 definition(compiler);
1787 consumeLine(compiler, "Expect newline after statement.");
1788 }
1789 while (peek(compiler) != TOKEN_RIGHT_BRACE && peek(compiler) != TOKEN_EOF);
1790
1791 consume(compiler, TOKEN_RIGHT_BRACE, "Expect '}' at end of block.");
1792 return false;
1793}
1794
1795// Parses a method or function body, after the initial "{" has been consumed.
1796//
1797// If [Compiler->isInitializer] is `true`, this is the body of a constructor
1798// initializer. In that case, this adds the code to ensure it returns `this`.
1799static void finishBody(Compiler* compiler)
1800{
1801 bool isExpressionBody = finishBlock(compiler);
1802
1803 if (compiler->isInitializer)
1804 {
1805 // If the initializer body evaluates to a value, discard it.
1806 if (isExpressionBody) emitOp(compiler, CODE_POP);
1807
1808 // The receiver is always stored in the first local slot.
1809 emitOp(compiler, CODE_LOAD_LOCAL_0);
1810 }
1811 else if (!isExpressionBody)
1812 {
1813 // Implicitly return null in statement bodies.
1814 emitOp(compiler, CODE_NULL);
1815 }
1816
1817 emitOp(compiler, CODE_RETURN);
1818}
1819
1820// The VM can only handle a certain number of parameters, so check that we
1821// haven't exceeded that and give a usable error.
1822static void validateNumParameters(Compiler* compiler, int numArgs)
1823{
1824 if (numArgs == MAX_PARAMETERS + 1)
1825 {
1826 // Only show an error at exactly max + 1 so that we can keep parsing the
1827 // parameters and minimize cascaded errors.
1828 error(compiler, "Methods cannot have more than %d parameters.",
1829 MAX_PARAMETERS);
1830 }
1831}
1832
1833// Parses the rest of a comma-separated parameter list after the opening
1834// delimeter. Updates `arity` in [signature] with the number of parameters.
1835static void finishParameterList(Compiler* compiler, Signature* signature)
1836{
1837 do
1838 {
1839 ignoreNewlines(compiler);
1840 validateNumParameters(compiler, ++signature->arity);
1841
1842 // Define a local variable in the method for the parameter.
1843 declareNamedVariable(compiler);
1844 }
1845 while (match(compiler, TOKEN_COMMA));
1846}
1847
1848// Gets the symbol for a method [name] with [length].
1849static int methodSymbol(Compiler* compiler, const char* name, int length)
1850{
1851 return wrenSymbolTableEnsure(compiler->parser->vm,
1852 &compiler->parser->vm->methodNames, name, length);
1853}
1854
1855// Appends characters to [name] (and updates [length]) for [numParams] "_"
1856// surrounded by [leftBracket] and [rightBracket].
1857static void signatureParameterList(char name[MAX_METHOD_SIGNATURE], int* length,
1858 int numParams, char leftBracket, char rightBracket)
1859{
1860 name[(*length)++] = leftBracket;
1861
1862 // This function may be called with too many parameters. When that happens,
1863 // a compile error has already been reported, but we need to make sure we
1864 // don't overflow the string too, hence the MAX_PARAMETERS check.
1865 for (int i = 0; i < numParams && i < MAX_PARAMETERS; i++)
1866 {
1867 if (i > 0) name[(*length)++] = ',';
1868 name[(*length)++] = '_';
1869 }
1870 name[(*length)++] = rightBracket;
1871}
1872
1873// Fills [name] with the stringified version of [signature] and updates
1874// [length] to the resulting length.
1875static void signatureToString(Signature* signature,
1876 char name[MAX_METHOD_SIGNATURE], int* length)
1877{
1878 *length = 0;
1879
1880 // Build the full name from the signature.
1881 memcpy(name + *length, signature->name, signature->length);
1882 *length += signature->length;
1883
1884 switch (signature->type)
1885 {
1886 case SIG_METHOD:
1887 signatureParameterList(name, length, signature->arity, '(', ')');
1888 break;
1889
1890 case SIG_GETTER:
1891 // The signature is just the name.
1892 break;
1893
1894 case SIG_SETTER:
1895 name[(*length)++] = '=';
1896 signatureParameterList(name, length, 1, '(', ')');
1897 break;
1898
1899 case SIG_SUBSCRIPT:
1900 signatureParameterList(name, length, signature->arity, '[', ']');
1901 break;
1902
1903 case SIG_SUBSCRIPT_SETTER:
1904 signatureParameterList(name, length, signature->arity - 1, '[', ']');
1905 name[(*length)++] = '=';
1906 signatureParameterList(name, length, 1, '(', ')');
1907 break;
1908
1909 case SIG_INITIALIZER:
1910 memcpy(name, "init ", 5);
1911 memcpy(name + 5, signature->name, signature->length);
1912 *length = 5 + signature->length;
1913 signatureParameterList(name, length, signature->arity, '(', ')');
1914 break;
1915 }
1916
1917 name[*length] = '\0';
1918}
1919
1920// Gets the symbol for a method with [signature].
1921static int signatureSymbol(Compiler* compiler, Signature* signature)
1922{
1923 // Build the full name from the signature.
1924 char name[MAX_METHOD_SIGNATURE];
1925 int length;
1926 signatureToString(signature, name, &length);
1927
1928 return methodSymbol(compiler, name, length);
1929}
1930
1931// Returns a signature with [type] whose name is from the last consumed token.
1932static Signature signatureFromToken(Compiler* compiler, SignatureType type)
1933{
1934 Signature signature;
1935
1936 // Get the token for the method name.
1937 Token* token = &compiler->parser->previous;
1938 signature.name = token->start;
1939 signature.length = token->length;
1940 signature.type = type;
1941 signature.arity = 0;
1942
1943 if (signature.length > MAX_METHOD_NAME)
1944 {
1945 error(compiler, "Method names cannot be longer than %d characters.",
1946 MAX_METHOD_NAME);
1947 signature.length = MAX_METHOD_NAME;
1948 }
1949
1950 return signature;
1951}
1952
1953// Parses a comma-separated list of arguments. Modifies [signature] to include
1954// the arity of the argument list.
1955static void finishArgumentList(Compiler* compiler, Signature* signature)
1956{
1957 do
1958 {
1959 ignoreNewlines(compiler);
1960 validateNumParameters(compiler, ++signature->arity);
1961 expression(compiler);
1962 }
1963 while (match(compiler, TOKEN_COMMA));
1964
1965 // Allow a newline before the closing delimiter.
1966 ignoreNewlines(compiler);
1967}
1968
1969// Compiles a method call with [signature] using [instruction].
1970static void callSignature(Compiler* compiler, Code instruction,
1971 Signature* signature)
1972{
1973 int symbol = signatureSymbol(compiler, signature);
1974 emitShortArg(compiler, (Code)(instruction + signature->arity), symbol);
1975
1976 if (instruction == CODE_SUPER_0)
1977 {
1978 // Super calls need to be statically bound to the class's superclass. This
1979 // ensures we call the right method even when a method containing a super
1980 // call is inherited by another subclass.
1981 //
1982 // We bind it at class definition time by storing a reference to the
1983 // superclass in a constant. So, here, we create a slot in the constant
1984 // table and store NULL in it. When the method is bound, we'll look up the
1985 // superclass then and store it in the constant slot.
1986 emitShort(compiler, addConstant(compiler, NULL_VAL));
1987 }
1988}
1989
1990// Compiles a method call with [numArgs] for a method with [name] with [length].
1991static void callMethod(Compiler* compiler, int numArgs, const char* name,
1992 int length)
1993{
1994 int symbol = methodSymbol(compiler, name, length);
1995 emitShortArg(compiler, (Code)(CODE_CALL_0 + numArgs), symbol);
1996}
1997
1998// Compiles an (optional) argument list for a method call with [methodSignature]
1999// and then calls it.
2000static void methodCall(Compiler* compiler, Code instruction,
2001 Signature* signature)
2002{
2003 // Make a new signature that contains the updated arity and type based on
2004 // the arguments we find.
2005 Signature called = { signature->name, signature->length, SIG_GETTER, 0 };
2006
2007 // Parse the argument list, if any.
2008 if (match(compiler, TOKEN_LEFT_PAREN))
2009 {
2010 called.type = SIG_METHOD;
2011
2012 // Allow new line before an empty argument list
2013 ignoreNewlines(compiler);
2014
2015 // Allow empty an argument list.
2016 if (peek(compiler) != TOKEN_RIGHT_PAREN)
2017 {
2018 finishArgumentList(compiler, &called);
2019 }
2020 consume(compiler, TOKEN_RIGHT_PAREN, "Expect ')' after arguments.");
2021 }
2022
2023 // Parse the block argument, if any.
2024 if (match(compiler, TOKEN_LEFT_BRACE))
2025 {
2026 // Include the block argument in the arity.
2027 called.type = SIG_METHOD;
2028 called.arity++;
2029
2030 Compiler fnCompiler;
2031 initCompiler(&fnCompiler, compiler->parser, compiler, false);
2032
2033 // Make a dummy signature to track the arity.
2034 Signature fnSignature = { "", 0, SIG_METHOD, 0 };
2035
2036 // Parse the parameter list, if any.
2037 if (match(compiler, TOKEN_PIPE))
2038 {
2039 finishParameterList(&fnCompiler, &fnSignature);
2040 consume(compiler, TOKEN_PIPE, "Expect '|' after function parameters.");
2041 }
2042
2043 fnCompiler.fn->arity = fnSignature.arity;
2044
2045 finishBody(&fnCompiler);
2046
2047 // Name the function based on the method its passed to.
2048 char blockName[MAX_METHOD_SIGNATURE + 15];
2049 int blockLength;
2050 signatureToString(&called, blockName, &blockLength);
2051 memmove(blockName + blockLength, " block argument", 16);
2052
2053 endCompiler(&fnCompiler, blockName, blockLength + 15);
2054 }
2055
2056 // TODO: Allow Grace-style mixfix methods?
2057
2058 // If this is a super() call for an initializer, make sure we got an actual
2059 // argument list.
2060 if (signature->type == SIG_INITIALIZER)
2061 {
2062 if (called.type != SIG_METHOD)
2063 {
2064 error(compiler, "A superclass constructor must have an argument list.");
2065 }
2066
2067 called.type = SIG_INITIALIZER;
2068 }
2069
2070 callSignature(compiler, instruction, &called);
2071}
2072
2073// Compiles a call whose name is the previously consumed token. This includes
2074// getters, method calls with arguments, and setter calls.
2075static void namedCall(Compiler* compiler, bool canAssign, Code instruction)
2076{
2077 // Get the token for the method name.
2078 Signature signature = signatureFromToken(compiler, SIG_GETTER);
2079
2080 if (canAssign && match(compiler, TOKEN_EQ))
2081 {
2082 ignoreNewlines(compiler);
2083
2084 // Build the setter signature.
2085 signature.type = SIG_SETTER;
2086 signature.arity = 1;
2087
2088 // Compile the assigned value.
2089 expression(compiler);
2090 callSignature(compiler, instruction, &signature);
2091 }
2092 else
2093 {
2094 methodCall(compiler, instruction, &signature);
2095 allowLineBeforeDot(compiler);
2096 }
2097}
2098
2099// Emits the code to load [variable] onto the stack.
2100static void loadVariable(Compiler* compiler, Variable variable)
2101{
2102 switch (variable.scope)
2103 {
2104 case SCOPE_LOCAL:
2105 loadLocal(compiler, variable.index);
2106 break;
2107 case SCOPE_UPVALUE:
2108 emitByteArg(compiler, CODE_LOAD_UPVALUE, variable.index);
2109 break;
2110 case SCOPE_MODULE:
2111 emitShortArg(compiler, CODE_LOAD_MODULE_VAR, variable.index);
2112 break;
2113 default:
2114 UNREACHABLE();
2115 }
2116}
2117
2118// Loads the receiver of the currently enclosing method. Correctly handles
2119// functions defined inside methods.
2120static void loadThis(Compiler* compiler)
2121{
2122 loadVariable(compiler, resolveNonmodule(compiler, "this", 4));
2123}
2124
2125// Pushes the value for a module-level variable implicitly imported from core.
2126static void loadCoreVariable(Compiler* compiler, const char* name)
2127{
2128 int symbol = wrenSymbolTableFind(&compiler->parser->module->variableNames,
2129 name, strlen(name));
2130 ASSERT(symbol != -1, "Should have already defined core name.");
2131 emitShortArg(compiler, CODE_LOAD_MODULE_VAR, symbol);
2132}
2133
2134// A parenthesized expression.
2135static void grouping(Compiler* compiler, bool canAssign)
2136{
2137 expression(compiler);
2138 consume(compiler, TOKEN_RIGHT_PAREN, "Expect ')' after expression.");
2139}
2140
2141// A list literal.
2142static void list(Compiler* compiler, bool canAssign)
2143{
2144 // Instantiate a new list.
2145 loadCoreVariable(compiler, "List");
2146 callMethod(compiler, 0, "new()", 5);
2147
2148 // Compile the list elements. Each one compiles to a ".add()" call.
2149 do
2150 {
2151 ignoreNewlines(compiler);
2152
2153 // Stop if we hit the end of the list.
2154 if (peek(compiler) == TOKEN_RIGHT_BRACKET) break;
2155
2156 // The element.
2157 expression(compiler);
2158 callMethod(compiler, 1, "addCore_(_)", 11);
2159 } while (match(compiler, TOKEN_COMMA));
2160
2161 // Allow newlines before the closing ']'.
2162 ignoreNewlines(compiler);
2163 consume(compiler, TOKEN_RIGHT_BRACKET, "Expect ']' after list elements.");
2164}
2165
2166// A map literal.
2167static void map(Compiler* compiler, bool canAssign)
2168{
2169 // Instantiate a new map.
2170 loadCoreVariable(compiler, "Map");
2171 callMethod(compiler, 0, "new()", 5);
2172
2173 // Compile the map elements. Each one is compiled to just invoke the
2174 // subscript setter on the map.
2175 do
2176 {
2177 ignoreNewlines(compiler);
2178
2179 // Stop if we hit the end of the map.
2180 if (peek(compiler) == TOKEN_RIGHT_BRACE) break;
2181
2182 // The key.
2183 parsePrecedence(compiler, PREC_UNARY);
2184 consume(compiler, TOKEN_COLON, "Expect ':' after map key.");
2185 ignoreNewlines(compiler);
2186
2187 // The value.
2188 expression(compiler);
2189 callMethod(compiler, 2, "addCore_(_,_)", 13);
2190 } while (match(compiler, TOKEN_COMMA));
2191
2192 // Allow newlines before the closing '}'.
2193 ignoreNewlines(compiler);
2194 consume(compiler, TOKEN_RIGHT_BRACE, "Expect '}' after map entries.");
2195}
2196
2197// Unary operators like `-foo`.
2198static void unaryOp(Compiler* compiler, bool canAssign)
2199{
2200 GrammarRule* rule = getRule(compiler->parser->previous.type);
2201
2202 ignoreNewlines(compiler);
2203
2204 // Compile the argument.
2205 parsePrecedence(compiler, (Precedence)(PREC_UNARY + 1));
2206
2207 // Call the operator method on the left-hand side.
2208 callMethod(compiler, 0, rule->name, 1);
2209}
2210
2211static void boolean(Compiler* compiler, bool canAssign)
2212{
2213 emitOp(compiler,
2214 compiler->parser->previous.type == TOKEN_FALSE ? CODE_FALSE : CODE_TRUE);
2215}
2216
2217// Walks the compiler chain to find the compiler for the nearest class
2218// enclosing this one. Returns NULL if not currently inside a class definition.
2219static Compiler* getEnclosingClassCompiler(Compiler* compiler)
2220{
2221 while (compiler != NULL)
2222 {
2223 if (compiler->enclosingClass != NULL) return compiler;
2224 compiler = compiler->parent;
2225 }
2226
2227 return NULL;
2228}
2229
2230// Walks the compiler chain to find the nearest class enclosing this one.
2231// Returns NULL if not currently inside a class definition.
2232static ClassInfo* getEnclosingClass(Compiler* compiler)
2233{
2234 compiler = getEnclosingClassCompiler(compiler);
2235 return compiler == NULL ? NULL : compiler->enclosingClass;
2236}
2237
2238static void field(Compiler* compiler, bool canAssign)
2239{
2240 // Initialize it with a fake value so we can keep parsing and minimize the
2241 // number of cascaded errors.
2242 int field = MAX_FIELDS;
2243
2244 ClassInfo* enclosingClass = getEnclosingClass(compiler);
2245
2246 if (enclosingClass == NULL)
2247 {
2248 error(compiler, "Cannot reference a field outside of a class definition.");
2249 }
2250 else if (enclosingClass->isForeign)
2251 {
2252 error(compiler, "Cannot define fields in a foreign class.");
2253 }
2254 else if (enclosingClass->inStatic)
2255 {
2256 error(compiler, "Cannot use an instance field in a static method.");
2257 }
2258 else
2259 {
2260 // Look up the field, or implicitly define it.
2261 field = wrenSymbolTableEnsure(compiler->parser->vm, &enclosingClass->fields,
2262 compiler->parser->previous.start,
2263 compiler->parser->previous.length);
2264
2265 if (field >= MAX_FIELDS)
2266 {
2267 error(compiler, "A class can only have %d fields.", MAX_FIELDS);
2268 }
2269 }
2270
2271 // If there's an "=" after a field name, it's an assignment.
2272 bool isLoad = true;
2273 if (canAssign && match(compiler, TOKEN_EQ))
2274 {
2275 // Compile the right-hand side.
2276 expression(compiler);
2277 isLoad = false;
2278 }
2279
2280 // If we're directly inside a method, use a more optimal instruction.
2281 if (compiler->parent != NULL &&
2282 compiler->parent->enclosingClass == enclosingClass)
2283 {
2284 emitByteArg(compiler, isLoad ? CODE_LOAD_FIELD_THIS : CODE_STORE_FIELD_THIS,
2285 field);
2286 }
2287 else
2288 {
2289 loadThis(compiler);
2290 emitByteArg(compiler, isLoad ? CODE_LOAD_FIELD : CODE_STORE_FIELD, field);
2291 }
2292
2293 allowLineBeforeDot(compiler);
2294}
2295
2296// Compiles a read or assignment to [variable].
2297static void bareName(Compiler* compiler, bool canAssign, Variable variable)
2298{
2299 // If there's an "=" after a bare name, it's a variable assignment.
2300 if (canAssign && match(compiler, TOKEN_EQ))
2301 {
2302 // Compile the right-hand side.
2303 expression(compiler);
2304
2305 // Emit the store instruction.
2306 switch (variable.scope)
2307 {
2308 case SCOPE_LOCAL:
2309 emitByteArg(compiler, CODE_STORE_LOCAL, variable.index);
2310 break;
2311 case SCOPE_UPVALUE:
2312 emitByteArg(compiler, CODE_STORE_UPVALUE, variable.index);
2313 break;
2314 case SCOPE_MODULE:
2315 emitShortArg(compiler, CODE_STORE_MODULE_VAR, variable.index);
2316 break;
2317 default:
2318 UNREACHABLE();
2319 }
2320 return;
2321 }
2322
2323 // Emit the load instruction.
2324 loadVariable(compiler, variable);
2325
2326 allowLineBeforeDot(compiler);
2327}
2328
2329static void staticField(Compiler* compiler, bool canAssign)
2330{
2331 Compiler* classCompiler = getEnclosingClassCompiler(compiler);
2332 if (classCompiler == NULL)
2333 {
2334 error(compiler, "Cannot use a static field outside of a class definition.");
2335 return;
2336 }
2337
2338 // Look up the name in the scope chain.
2339 Token* token = &compiler->parser->previous;
2340
2341 // If this is the first time we've seen this static field, implicitly
2342 // define it as a variable in the scope surrounding the class definition.
2343 if (resolveLocal(classCompiler, token->start, token->length) == -1)
2344 {
2345 int symbol = declareVariable(classCompiler, NULL);
2346
2347 // Implicitly initialize it to null.
2348 emitOp(classCompiler, CODE_NULL);
2349 defineVariable(classCompiler, symbol);
2350 }
2351
2352 // It definitely exists now, so resolve it properly. This is different from
2353 // the above resolveLocal() call because we may have already closed over it
2354 // as an upvalue.
2355 Variable variable = resolveName(compiler, token->start, token->length);
2356 bareName(compiler, canAssign, variable);
2357}
2358
2359// Compiles a variable name or method call with an implicit receiver.
2360static void name(Compiler* compiler, bool canAssign)
2361{
2362 // Look for the name in the scope chain up to the nearest enclosing method.
2363 Token* token = &compiler->parser->previous;
2364
2365 Variable variable = resolveNonmodule(compiler, token->start, token->length);
2366 if (variable.index != -1)
2367 {
2368 bareName(compiler, canAssign, variable);
2369 return;
2370 }
2371
2372 // TODO: The fact that we return above here if the variable is known and parse
2373 // an optional argument list below if not means that the grammar is not
2374 // context-free. A line of code in a method like "someName(foo)" is a parse
2375 // error if "someName" is a defined variable in the surrounding scope and not
2376 // if it isn't. Fix this. One option is to have "someName(foo)" always
2377 // resolve to a self-call if there is an argument list, but that makes
2378 // getters a little confusing.
2379
2380 // If we're inside a method and the name is lowercase, treat it as a method
2381 // on this.
2382 if (wrenIsLocalName(token->start) && getEnclosingClass(compiler) != NULL)
2383 {
2384 loadThis(compiler);
2385 namedCall(compiler, canAssign, CODE_CALL_0);
2386 return;
2387 }
2388
2389 // Otherwise, look for a module-level variable with the name.
2390 variable.scope = SCOPE_MODULE;
2391 variable.index = wrenSymbolTableFind(&compiler->parser->module->variableNames,
2392 token->start, token->length);
2393 if (variable.index == -1)
2394 {
2395 // Implicitly define a module-level variable in
2396 // the hopes that we get a real definition later.
2397 variable.index = wrenDeclareVariable(compiler->parser->vm,
2398 compiler->parser->module,
2399 token->start, token->length,
2400 token->line);
2401
2402 if (variable.index == -2)
2403 {
2404 error(compiler, "Too many module variables defined.");
2405 }
2406 }
2407
2408 bareName(compiler, canAssign, variable);
2409}
2410
2411static void null(Compiler* compiler, bool canAssign)
2412{
2413 emitOp(compiler, CODE_NULL);
2414}
2415
2416// A number or string literal.
2417static void literal(Compiler* compiler, bool canAssign)
2418{
2419 emitConstant(compiler, compiler->parser->previous.value);
2420}
2421
2422// A string literal that contains interpolated expressions.
2423//
2424// Interpolation is syntactic sugar for calling ".join()" on a list. So the
2425// string:
2426//
2427// "a %(b + c) d"
2428//
2429// is compiled roughly like:
2430//
2431// ["a ", b + c, " d"].join()
2432static void stringInterpolation(Compiler* compiler, bool canAssign)
2433{
2434 // Instantiate a new list.
2435 loadCoreVariable(compiler, "List");
2436 callMethod(compiler, 0, "new()", 5);
2437
2438 do
2439 {
2440 // The opening string part.
2441 literal(compiler, false);
2442 callMethod(compiler, 1, "addCore_(_)", 11);
2443
2444 // The interpolated expression.
2445 ignoreNewlines(compiler);
2446 expression(compiler);
2447 callMethod(compiler, 1, "addCore_(_)", 11);
2448
2449 ignoreNewlines(compiler);
2450 } while (match(compiler, TOKEN_INTERPOLATION));
2451
2452 // The trailing string part.
2453 consume(compiler, TOKEN_STRING, "Expect end of string interpolation.");
2454 literal(compiler, false);
2455 callMethod(compiler, 1, "addCore_(_)", 11);
2456
2457 // The list of interpolated parts.
2458 callMethod(compiler, 0, "join()", 6);
2459}
2460
2461static void super_(Compiler* compiler, bool canAssign)
2462{
2463 ClassInfo* enclosingClass = getEnclosingClass(compiler);
2464 if (enclosingClass == NULL)
2465 {
2466 error(compiler, "Cannot use 'super' outside of a method.");
2467 }
2468
2469 loadThis(compiler);
2470
2471 // TODO: Super operator calls.
2472 // TODO: There's no syntax for invoking a superclass constructor with a
2473 // different name from the enclosing one. Figure that out.
2474
2475 // See if it's a named super call, or an unnamed one.
2476 if (match(compiler, TOKEN_DOT))
2477 {
2478 // Compile the superclass call.
2479 consume(compiler, TOKEN_NAME, "Expect method name after 'super.'.");
2480 namedCall(compiler, canAssign, CODE_SUPER_0);
2481 }
2482 else if (enclosingClass != NULL)
2483 {
2484 // No explicit name, so use the name of the enclosing method. Make sure we
2485 // check that enclosingClass isn't NULL first. We've already reported the
2486 // error, but we don't want to crash here.
2487 methodCall(compiler, CODE_SUPER_0, enclosingClass->signature);
2488 }
2489}
2490
2491static void this_(Compiler* compiler, bool canAssign)
2492{
2493 if (getEnclosingClass(compiler) == NULL)
2494 {
2495 error(compiler, "Cannot use 'this' outside of a method.");
2496 return;
2497 }
2498
2499 loadThis(compiler);
2500}
2501
2502// Subscript or "array indexing" operator like `foo[bar]`.
2503static void subscript(Compiler* compiler, bool canAssign)
2504{
2505 Signature signature = { "", 0, SIG_SUBSCRIPT, 0 };
2506
2507 // Parse the argument list.
2508 finishArgumentList(compiler, &signature);
2509 consume(compiler, TOKEN_RIGHT_BRACKET, "Expect ']' after arguments.");
2510
2511 allowLineBeforeDot(compiler);
2512
2513 if (canAssign && match(compiler, TOKEN_EQ))
2514 {
2515 signature.type = SIG_SUBSCRIPT_SETTER;
2516
2517 // Compile the assigned value.
2518 validateNumParameters(compiler, ++signature.arity);
2519 expression(compiler);
2520 }
2521
2522 callSignature(compiler, CODE_CALL_0, &signature);
2523}
2524
2525static void call(Compiler* compiler, bool canAssign)
2526{
2527 ignoreNewlines(compiler);
2528 consume(compiler, TOKEN_NAME, "Expect method name after '.'.");
2529 namedCall(compiler, canAssign, CODE_CALL_0);
2530}
2531
2532static void and_(Compiler* compiler, bool canAssign)
2533{
2534 ignoreNewlines(compiler);
2535
2536 // Skip the right argument if the left is false.
2537 int jump = emitJump(compiler, CODE_AND);
2538 parsePrecedence(compiler, PREC_LOGICAL_AND);
2539 patchJump(compiler, jump);
2540}
2541
2542static void or_(Compiler* compiler, bool canAssign)
2543{
2544 ignoreNewlines(compiler);
2545
2546 // Skip the right argument if the left is true.
2547 int jump = emitJump(compiler, CODE_OR);
2548 parsePrecedence(compiler, PREC_LOGICAL_OR);
2549 patchJump(compiler, jump);
2550}
2551
2552static void conditional(Compiler* compiler, bool canAssign)
2553{
2554 // Ignore newline after '?'.
2555 ignoreNewlines(compiler);
2556
2557 // Jump to the else branch if the condition is false.
2558 int ifJump = emitJump(compiler, CODE_JUMP_IF);
2559
2560 // Compile the then branch.
2561 parsePrecedence(compiler, PREC_CONDITIONAL);
2562
2563 consume(compiler, TOKEN_COLON,
2564 "Expect ':' after then branch of conditional operator.");
2565 ignoreNewlines(compiler);
2566
2567 // Jump over the else branch when the if branch is taken.
2568 int elseJump = emitJump(compiler, CODE_JUMP);
2569
2570 // Compile the else branch.
2571 patchJump(compiler, ifJump);
2572
2573 parsePrecedence(compiler, PREC_ASSIGNMENT);
2574
2575 // Patch the jump over the else.
2576 patchJump(compiler, elseJump);
2577}
2578
2579void infixOp(Compiler* compiler, bool canAssign)
2580{
2581 GrammarRule* rule = getRule(compiler->parser->previous.type);
2582
2583 // An infix operator cannot end an expression.
2584 ignoreNewlines(compiler);
2585
2586 // Compile the right-hand side.
2587 parsePrecedence(compiler, (Precedence)(rule->precedence + 1));
2588
2589 // Call the operator method on the left-hand side.
2590 Signature signature = { rule->name, (int)strlen(rule->name), SIG_METHOD, 1 };
2591 callSignature(compiler, CODE_CALL_0, &signature);
2592}
2593
2594// Compiles a method signature for an infix operator.
2595void infixSignature(Compiler* compiler, Signature* signature)
2596{
2597 // Add the RHS parameter.
2598 signature->type = SIG_METHOD;
2599 signature->arity = 1;
2600
2601 // Parse the parameter name.
2602 consume(compiler, TOKEN_LEFT_PAREN, "Expect '(' after operator name.");
2603 declareNamedVariable(compiler);
2604 consume(compiler, TOKEN_RIGHT_PAREN, "Expect ')' after parameter name.");
2605}
2606
2607// Compiles a method signature for an unary operator (i.e. "!").
2608void unarySignature(Compiler* compiler, Signature* signature)
2609{
2610 // Do nothing. The name is already complete.
2611 signature->type = SIG_GETTER;
2612}
2613
2614// Compiles a method signature for an operator that can either be unary or
2615// infix (i.e. "-").
2616void mixedSignature(Compiler* compiler, Signature* signature)
2617{
2618 signature->type = SIG_GETTER;
2619
2620 // If there is a parameter, it's an infix operator, otherwise it's unary.
2621 if (match(compiler, TOKEN_LEFT_PAREN))
2622 {
2623 // Add the RHS parameter.
2624 signature->type = SIG_METHOD;
2625 signature->arity = 1;
2626
2627 // Parse the parameter name.
2628 declareNamedVariable(compiler);
2629 consume(compiler, TOKEN_RIGHT_PAREN, "Expect ')' after parameter name.");
2630 }
2631}
2632
2633// Compiles an optional setter parameter in a method [signature].
2634//
2635// Returns `true` if it was a setter.
2636static bool maybeSetter(Compiler* compiler, Signature* signature)
2637{
2638 // See if it's a setter.
2639 if (!match(compiler, TOKEN_EQ)) return false;
2640
2641 // It's a setter.
2642 if (signature->type == SIG_SUBSCRIPT)
2643 {
2644 signature->type = SIG_SUBSCRIPT_SETTER;
2645 }
2646 else
2647 {
2648 signature->type = SIG_SETTER;
2649 }
2650
2651 // Parse the value parameter.
2652 consume(compiler, TOKEN_LEFT_PAREN, "Expect '(' after '='.");
2653 declareNamedVariable(compiler);
2654 consume(compiler, TOKEN_RIGHT_PAREN, "Expect ')' after parameter name.");
2655
2656 signature->arity++;
2657
2658 return true;
2659}
2660
2661// Compiles a method signature for a subscript operator.
2662void subscriptSignature(Compiler* compiler, Signature* signature)
2663{
2664 signature->type = SIG_SUBSCRIPT;
2665
2666 // The signature currently has "[" as its name since that was the token that
2667 // matched it. Clear that out.
2668 signature->length = 0;
2669
2670 // Parse the parameters inside the subscript.
2671 finishParameterList(compiler, signature);
2672 consume(compiler, TOKEN_RIGHT_BRACKET, "Expect ']' after parameters.");
2673
2674 maybeSetter(compiler, signature);
2675}
2676
2677// Parses an optional parenthesized parameter list. Updates `type` and `arity`
2678// in [signature] to match what was parsed.
2679static void parameterList(Compiler* compiler, Signature* signature)
2680{
2681 // The parameter list is optional.
2682 if (!match(compiler, TOKEN_LEFT_PAREN)) return;
2683
2684 signature->type = SIG_METHOD;
2685
2686 // Allow new line before an empty argument list
2687 ignoreNewlines(compiler);
2688
2689 // Allow an empty parameter list.
2690 if (match(compiler, TOKEN_RIGHT_PAREN)) return;
2691
2692 finishParameterList(compiler, signature);
2693 consume(compiler, TOKEN_RIGHT_PAREN, "Expect ')' after parameters.");
2694}
2695
2696// Compiles a method signature for a named method or setter.
2697void namedSignature(Compiler* compiler, Signature* signature)
2698{
2699 signature->type = SIG_GETTER;
2700
2701 // If it's a setter, it can't also have a parameter list.
2702 if (maybeSetter(compiler, signature)) return;
2703
2704 // Regular named method with an optional parameter list.
2705 parameterList(compiler, signature);
2706}
2707
2708// Compiles a method signature for a constructor.
2709void constructorSignature(Compiler* compiler, Signature* signature)
2710{
2711 consume(compiler, TOKEN_NAME, "Expect constructor name after 'construct'.");
2712
2713 // Capture the name.
2714 *signature = signatureFromToken(compiler, SIG_INITIALIZER);
2715
2716 if (match(compiler, TOKEN_EQ))
2717 {
2718 error(compiler, "A constructor cannot be a setter.");
2719 }
2720
2721 if (!match(compiler, TOKEN_LEFT_PAREN))
2722 {
2723 error(compiler, "A constructor cannot be a getter.");
2724 return;
2725 }
2726
2727 // Allow an empty parameter list.
2728 if (match(compiler, TOKEN_RIGHT_PAREN)) return;
2729
2730 finishParameterList(compiler, signature);
2731 consume(compiler, TOKEN_RIGHT_PAREN, "Expect ')' after parameters.");
2732}
2733
2734// This table defines all of the parsing rules for the prefix and infix
2735// expressions in the grammar. Expressions are parsed using a Pratt parser.
2736//
2737// See: http://journal.stuffwithstuff.com/2011/03/19/pratt-parsers-expression-parsing-made-easy/
2738#define UNUSED { NULL, NULL, NULL, PREC_NONE, NULL }
2739#define PREFIX(fn) { fn, NULL, NULL, PREC_NONE, NULL }
2740#define INFIX(prec, fn) { NULL, fn, NULL, prec, NULL }
2741#define INFIX_OPERATOR(prec, name) { NULL, infixOp, infixSignature, prec, name }
2742#define PREFIX_OPERATOR(name) { unaryOp, NULL, unarySignature, PREC_NONE, name }
2743#define OPERATOR(name) { unaryOp, infixOp, mixedSignature, PREC_TERM, name }
2744
2745GrammarRule rules[] =
2746{
2747 /* TOKEN_LEFT_PAREN */ PREFIX(grouping),
2748 /* TOKEN_RIGHT_PAREN */ UNUSED,
2749 /* TOKEN_LEFT_BRACKET */ { list, subscript, subscriptSignature, PREC_CALL, NULL },
2750 /* TOKEN_RIGHT_BRACKET */ UNUSED,
2751 /* TOKEN_LEFT_BRACE */ PREFIX(map),
2752 /* TOKEN_RIGHT_BRACE */ UNUSED,
2753 /* TOKEN_COLON */ UNUSED,
2754 /* TOKEN_DOT */ INFIX(PREC_CALL, call),
2755 /* TOKEN_DOTDOT */ INFIX_OPERATOR(PREC_RANGE, ".."),
2756 /* TOKEN_DOTDOTDOT */ INFIX_OPERATOR(PREC_RANGE, "..."),
2757 /* TOKEN_COMMA */ UNUSED,
2758 /* TOKEN_STAR */ INFIX_OPERATOR(PREC_FACTOR, "*"),
2759 /* TOKEN_SLASH */ INFIX_OPERATOR(PREC_FACTOR, "/"),
2760 /* TOKEN_PERCENT */ INFIX_OPERATOR(PREC_FACTOR, "%"),
2761 /* TOKEN_HASH */ UNUSED,
2762 /* TOKEN_PLUS */ INFIX_OPERATOR(PREC_TERM, "+"),
2763 /* TOKEN_MINUS */ OPERATOR("-"),
2764 /* TOKEN_LTLT */ INFIX_OPERATOR(PREC_BITWISE_SHIFT, "<<"),
2765 /* TOKEN_GTGT */ INFIX_OPERATOR(PREC_BITWISE_SHIFT, ">>"),
2766 /* TOKEN_PIPE */ INFIX_OPERATOR(PREC_BITWISE_OR, "|"),
2767 /* TOKEN_PIPEPIPE */ INFIX(PREC_LOGICAL_OR, or_),
2768 /* TOKEN_CARET */ INFIX_OPERATOR(PREC_BITWISE_XOR, "^"),
2769 /* TOKEN_AMP */ INFIX_OPERATOR(PREC_BITWISE_AND, "&"),
2770 /* TOKEN_AMPAMP */ INFIX(PREC_LOGICAL_AND, and_),
2771 /* TOKEN_BANG */ PREFIX_OPERATOR("!"),
2772 /* TOKEN_TILDE */ PREFIX_OPERATOR("~"),
2773 /* TOKEN_QUESTION */ INFIX(PREC_ASSIGNMENT, conditional),
2774 /* TOKEN_EQ */ UNUSED,
2775 /* TOKEN_LT */ INFIX_OPERATOR(PREC_COMPARISON, "<"),
2776 /* TOKEN_GT */ INFIX_OPERATOR(PREC_COMPARISON, ">"),
2777 /* TOKEN_LTEQ */ INFIX_OPERATOR(PREC_COMPARISON, "<="),
2778 /* TOKEN_GTEQ */ INFIX_OPERATOR(PREC_COMPARISON, ">="),
2779 /* TOKEN_EQEQ */ INFIX_OPERATOR(PREC_EQUALITY, "=="),
2780 /* TOKEN_BANGEQ */ INFIX_OPERATOR(PREC_EQUALITY, "!="),
2781 /* TOKEN_BREAK */ UNUSED,
2782 /* TOKEN_CONTINUE */ UNUSED,
2783 /* TOKEN_CLASS */ UNUSED,
2784 /* TOKEN_CONSTRUCT */ { NULL, NULL, constructorSignature, PREC_NONE, NULL },
2785 /* TOKEN_ELSE */ UNUSED,
2786 /* TOKEN_FALSE */ PREFIX(boolean),
2787 /* TOKEN_FOR */ UNUSED,
2788 /* TOKEN_FOREIGN */ UNUSED,
2789 /* TOKEN_IF */ UNUSED,
2790 /* TOKEN_IMPORT */ UNUSED,
2791 /* TOKEN_AS */ UNUSED,
2792 /* TOKEN_IN */ UNUSED,
2793 /* TOKEN_IS */ INFIX_OPERATOR(PREC_IS, "is"),
2794 /* TOKEN_NULL */ PREFIX(null),
2795 /* TOKEN_RETURN */ UNUSED,
2796 /* TOKEN_STATIC */ UNUSED,
2797 /* TOKEN_SUPER */ PREFIX(super_),
2798 /* TOKEN_THIS */ PREFIX(this_),
2799 /* TOKEN_TRUE */ PREFIX(boolean),
2800 /* TOKEN_VAR */ UNUSED,
2801 /* TOKEN_WHILE */ UNUSED,
2802 /* TOKEN_FIELD */ PREFIX(field),
2803 /* TOKEN_STATIC_FIELD */ PREFIX(staticField),
2804 /* TOKEN_NAME */ { name, NULL, namedSignature, PREC_NONE, NULL },
2805 /* TOKEN_NUMBER */ PREFIX(literal),
2806 /* TOKEN_STRING */ PREFIX(literal),
2807 /* TOKEN_INTERPOLATION */ PREFIX(stringInterpolation),
2808 /* TOKEN_LINE */ UNUSED,
2809 /* TOKEN_ERROR */ UNUSED,
2810 /* TOKEN_EOF */ UNUSED
2811};
2812
2813// Gets the [GrammarRule] associated with tokens of [type].
2814static GrammarRule* getRule(TokenType type)
2815{
2816 return &rules[type];
2817}
2818
2819// The main entrypoint for the top-down operator precedence parser.
2820void parsePrecedence(Compiler* compiler, Precedence precedence)
2821{
2822 nextToken(compiler->parser);
2823 GrammarFn prefix = rules[compiler->parser->previous.type].prefix;
2824
2825 if (prefix == NULL)
2826 {
2827 error(compiler, "Expected expression.");
2828 return;
2829 }
2830
2831 // Track if the precendence of the surrounding expression is low enough to
2832 // allow an assignment inside this one. We can't compile an assignment like
2833 // a normal expression because it requires us to handle the LHS specially --
2834 // it needs to be an lvalue, not an rvalue. So, for each of the kinds of
2835 // expressions that are valid lvalues -- names, subscripts, fields, etc. --
2836 // we pass in whether or not it appears in a context loose enough to allow
2837 // "=". If so, it will parse the "=" itself and handle it appropriately.
2838 bool canAssign = precedence <= PREC_CONDITIONAL;
2839 prefix(compiler, canAssign);
2840
2841 while (precedence <= rules[compiler->parser->current.type].precedence)
2842 {
2843 nextToken(compiler->parser);
2844 GrammarFn infix = rules[compiler->parser->previous.type].infix;
2845 infix(compiler, canAssign);
2846 }
2847}
2848
2849// Parses an expression. Unlike statements, expressions leave a resulting value
2850// on the stack.
2851void expression(Compiler* compiler)
2852{
2853 parsePrecedence(compiler, PREC_LOWEST);
2854}
2855
2856// Returns the number of bytes for the arguments to the instruction
2857// at [ip] in [fn]'s bytecode.
2858static int getByteCountForArguments(const uint8_t* bytecode,
2859 const Value* constants, int ip)
2860{
2861 Code instruction = (Code)bytecode[ip];
2862 switch (instruction)
2863 {
2864 case CODE_NULL:
2865 case CODE_FALSE:
2866 case CODE_TRUE:
2867 case CODE_POP:
2868 case CODE_CLOSE_UPVALUE:
2869 case CODE_RETURN:
2870 case CODE_END:
2871 case CODE_LOAD_LOCAL_0:
2872 case CODE_LOAD_LOCAL_1:
2873 case CODE_LOAD_LOCAL_2:
2874 case CODE_LOAD_LOCAL_3:
2875 case CODE_LOAD_LOCAL_4:
2876 case CODE_LOAD_LOCAL_5:
2877 case CODE_LOAD_LOCAL_6:
2878 case CODE_LOAD_LOCAL_7:
2879 case CODE_LOAD_LOCAL_8:
2880 case CODE_CONSTRUCT:
2881 case CODE_FOREIGN_CONSTRUCT:
2882 case CODE_FOREIGN_CLASS:
2883 case CODE_END_MODULE:
2884 case CODE_END_CLASS:
2885 return 0;
2886
2887 case CODE_LOAD_LOCAL:
2888 case CODE_STORE_LOCAL:
2889 case CODE_LOAD_UPVALUE:
2890 case CODE_STORE_UPVALUE:
2891 case CODE_LOAD_FIELD_THIS:
2892 case CODE_STORE_FIELD_THIS:
2893 case CODE_LOAD_FIELD:
2894 case CODE_STORE_FIELD:
2895 case CODE_CLASS:
2896 return 1;
2897
2898 case CODE_CONSTANT:
2899 case CODE_LOAD_MODULE_VAR:
2900 case CODE_STORE_MODULE_VAR:
2901 case CODE_CALL_0:
2902 case CODE_CALL_1:
2903 case CODE_CALL_2:
2904 case CODE_CALL_3:
2905 case CODE_CALL_4:
2906 case CODE_CALL_5:
2907 case CODE_CALL_6:
2908 case CODE_CALL_7:
2909 case CODE_CALL_8:
2910 case CODE_CALL_9:
2911 case CODE_CALL_10:
2912 case CODE_CALL_11:
2913 case CODE_CALL_12:
2914 case CODE_CALL_13:
2915 case CODE_CALL_14:
2916 case CODE_CALL_15:
2917 case CODE_CALL_16:
2918 case CODE_JUMP:
2919 case CODE_LOOP:
2920 case CODE_JUMP_IF:
2921 case CODE_AND:
2922 case CODE_OR:
2923 case CODE_METHOD_INSTANCE:
2924 case CODE_METHOD_STATIC:
2925 case CODE_IMPORT_MODULE:
2926 case CODE_IMPORT_VARIABLE:
2927 return 2;
2928
2929 case CODE_SUPER_0:
2930 case CODE_SUPER_1:
2931 case CODE_SUPER_2:
2932 case CODE_SUPER_3:
2933 case CODE_SUPER_4:
2934 case CODE_SUPER_5:
2935 case CODE_SUPER_6:
2936 case CODE_SUPER_7:
2937 case CODE_SUPER_8:
2938 case CODE_SUPER_9:
2939 case CODE_SUPER_10:
2940 case CODE_SUPER_11:
2941 case CODE_SUPER_12:
2942 case CODE_SUPER_13:
2943 case CODE_SUPER_14:
2944 case CODE_SUPER_15:
2945 case CODE_SUPER_16:
2946 return 4;
2947
2948 case CODE_CLOSURE:
2949 {
2950 int constant = (bytecode[ip + 1] << 8) | bytecode[ip + 2];
2951 ObjFn* loadedFn = AS_FN(constants[constant]);
2952
2953 // There are two bytes for the constant, then two for each upvalue.
2954 return 2 + (loadedFn->numUpvalues * 2);
2955 }
2956 }
2957
2958 UNREACHABLE();
2959 return 0;
2960}
2961
2962// Marks the beginning of a loop. Keeps track of the current instruction so we
2963// know what to loop back to at the end of the body.
2964static void startLoop(Compiler* compiler, Loop* loop)
2965{
2966 loop->enclosing = compiler->loop;
2967 loop->start = compiler->fn->code.count - 1;
2968 loop->scopeDepth = compiler->scopeDepth;
2969 compiler->loop = loop;
2970}
2971
2972// Emits the [CODE_JUMP_IF] instruction used to test the loop condition and
2973// potentially exit the loop. Keeps track of the instruction so we can patch it
2974// later once we know where the end of the body is.
2975static void testExitLoop(Compiler* compiler)
2976{
2977 compiler->loop->exitJump = emitJump(compiler, CODE_JUMP_IF);
2978}
2979
2980// Compiles the body of the loop and tracks its extent so that contained "break"
2981// statements can be handled correctly.
2982static void loopBody(Compiler* compiler)
2983{
2984 compiler->loop->body = compiler->fn->code.count;
2985 statement(compiler);
2986}
2987
2988// Ends the current innermost loop. Patches up all jumps and breaks now that
2989// we know where the end of the loop is.
2990static void endLoop(Compiler* compiler)
2991{
2992 // We don't check for overflow here since the forward jump over the loop body
2993 // will report an error for the same problem.
2994 int loopOffset = compiler->fn->code.count - compiler->loop->start + 2;
2995 emitShortArg(compiler, CODE_LOOP, loopOffset);
2996
2997 patchJump(compiler, compiler->loop->exitJump);
2998
2999 // Find any break placeholder instructions (which will be CODE_END in the
3000 // bytecode) and replace them with real jumps.
3001 int i = compiler->loop->body;
3002 while (i < compiler->fn->code.count)
3003 {
3004 if (compiler->fn->code.data[i] == CODE_END)
3005 {
3006 compiler->fn->code.data[i] = CODE_JUMP;
3007 patchJump(compiler, i + 1);
3008 i += 3;
3009 }
3010 else
3011 {
3012 // Skip this instruction and its arguments.
3013 i += 1 + getByteCountForArguments(compiler->fn->code.data,
3014 compiler->fn->constants.data, i);
3015 }
3016 }
3017
3018 compiler->loop = compiler->loop->enclosing;
3019}
3020
3021static void forStatement(Compiler* compiler)
3022{
3023 // A for statement like:
3024 //
3025 // for (i in sequence.expression) {
3026 // System.print(i)
3027 // }
3028 //
3029 // Is compiled to bytecode almost as if the source looked like this:
3030 //
3031 // {
3032 // var seq_ = sequence.expression
3033 // var iter_
3034 // while (iter_ = seq_.iterate(iter_)) {
3035 // var i = seq_.iteratorValue(iter_)
3036 // System.print(i)
3037 // }
3038 // }
3039 //
3040 // It's not exactly this, because the synthetic variables `seq_` and `iter_`
3041 // actually get names that aren't valid Wren identfiers, but that's the basic
3042 // idea.
3043 //
3044 // The important parts are:
3045 // - The sequence expression is only evaluated once.
3046 // - The .iterate() method is used to advance the iterator and determine if
3047 // it should exit the loop.
3048 // - The .iteratorValue() method is used to get the value at the current
3049 // iterator position.
3050
3051 // Create a scope for the hidden local variables used for the iterator.
3052 pushScope(compiler);
3053
3054 consume(compiler, TOKEN_LEFT_PAREN, "Expect '(' after 'for'.");
3055 consume(compiler, TOKEN_NAME, "Expect for loop variable name.");
3056
3057 // Remember the name of the loop variable.
3058 const char* name = compiler->parser->previous.start;
3059 int length = compiler->parser->previous.length;
3060
3061 consume(compiler, TOKEN_IN, "Expect 'in' after loop variable.");
3062 ignoreNewlines(compiler);
3063
3064 // Evaluate the sequence expression and store it in a hidden local variable.
3065 // The space in the variable name ensures it won't collide with a user-defined
3066 // variable.
3067 expression(compiler);
3068
3069 // Verify that there is space to hidden local variables.
3070 // Note that we expect only two addLocal calls next to each other in the
3071 // following code.
3072 if (compiler->numLocals + 2 > MAX_LOCALS)
3073 {
3074 error(compiler, "Cannot declare more than %d variables in one scope. (Not enough space for for-loops internal variables)",
3075 MAX_LOCALS);
3076 return;
3077 }
3078 int seqSlot = addLocal(compiler, "seq ", 4);
3079
3080 // Create another hidden local for the iterator object.
3081 null(compiler, false);
3082 int iterSlot = addLocal(compiler, "iter ", 5);
3083
3084 consume(compiler, TOKEN_RIGHT_PAREN, "Expect ')' after loop expression.");
3085
3086 Loop loop;
3087 startLoop(compiler, &loop);
3088
3089 // Advance the iterator by calling the ".iterate" method on the sequence.
3090 loadLocal(compiler, seqSlot);
3091 loadLocal(compiler, iterSlot);
3092
3093 // Update and test the iterator.
3094 callMethod(compiler, 1, "iterate(_)", 10);
3095 emitByteArg(compiler, CODE_STORE_LOCAL, iterSlot);
3096 testExitLoop(compiler);
3097
3098 // Get the current value in the sequence by calling ".iteratorValue".
3099 loadLocal(compiler, seqSlot);
3100 loadLocal(compiler, iterSlot);
3101 callMethod(compiler, 1, "iteratorValue(_)", 16);
3102
3103 // Bind the loop variable in its own scope. This ensures we get a fresh
3104 // variable each iteration so that closures for it don't all see the same one.
3105 pushScope(compiler);
3106 addLocal(compiler, name, length);
3107
3108 loopBody(compiler);
3109
3110 // Loop variable.
3111 popScope(compiler);
3112
3113 endLoop(compiler);
3114
3115 // Hidden variables.
3116 popScope(compiler);
3117}
3118
3119static void ifStatement(Compiler* compiler)
3120{
3121 // Compile the condition.
3122 consume(compiler, TOKEN_LEFT_PAREN, "Expect '(' after 'if'.");
3123 expression(compiler);
3124 consume(compiler, TOKEN_RIGHT_PAREN, "Expect ')' after if condition.");
3125
3126 // Jump to the else branch if the condition is false.
3127 int ifJump = emitJump(compiler, CODE_JUMP_IF);
3128
3129 // Compile the then branch.
3130 statement(compiler);
3131
3132 // Compile the else branch if there is one.
3133 if (match(compiler, TOKEN_ELSE))
3134 {
3135 // Jump over the else branch when the if branch is taken.
3136 int elseJump = emitJump(compiler, CODE_JUMP);
3137 patchJump(compiler, ifJump);
3138
3139 statement(compiler);
3140
3141 // Patch the jump over the else.
3142 patchJump(compiler, elseJump);
3143 }
3144 else
3145 {
3146 patchJump(compiler, ifJump);
3147 }
3148}
3149
3150static void whileStatement(Compiler* compiler)
3151{
3152 Loop loop;
3153 startLoop(compiler, &loop);
3154
3155 // Compile the condition.
3156 consume(compiler, TOKEN_LEFT_PAREN, "Expect '(' after 'while'.");
3157 expression(compiler);
3158 consume(compiler, TOKEN_RIGHT_PAREN, "Expect ')' after while condition.");
3159
3160 testExitLoop(compiler);
3161 loopBody(compiler);
3162 endLoop(compiler);
3163}
3164
3165// Compiles a simple statement. These can only appear at the top-level or
3166// within curly blocks. Simple statements exclude variable binding statements
3167// like "var" and "class" which are not allowed directly in places like the
3168// branches of an "if" statement.
3169//
3170// Unlike expressions, statements do not leave a value on the stack.
3171void statement(Compiler* compiler)
3172{
3173 if (match(compiler, TOKEN_BREAK))
3174 {
3175 if (compiler->loop == NULL)
3176 {
3177 error(compiler, "Cannot use 'break' outside of a loop.");
3178 return;
3179 }
3180
3181 // Since we will be jumping out of the scope, make sure any locals in it
3182 // are discarded first.
3183 discardLocals(compiler, compiler->loop->scopeDepth + 1);
3184
3185 // Emit a placeholder instruction for the jump to the end of the body. When
3186 // we're done compiling the loop body and know where the end is, we'll
3187 // replace these with `CODE_JUMP` instructions with appropriate offsets.
3188 // We use `CODE_END` here because that can't occur in the middle of
3189 // bytecode.
3190 emitJump(compiler, CODE_END);
3191 }
3192 else if (match(compiler, TOKEN_CONTINUE))
3193 {
3194 if (compiler->loop == NULL)
3195 {
3196 error(compiler, "Cannot use 'continue' outside of a loop.");
3197 return;
3198 }
3199
3200 // Since we will be jumping out of the scope, make sure any locals in it
3201 // are discarded first.
3202 discardLocals(compiler, compiler->loop->scopeDepth + 1);
3203
3204 // emit a jump back to the top of the loop
3205 int loopOffset = compiler->fn->code.count - compiler->loop->start + 2;
3206 emitShortArg(compiler, CODE_LOOP, loopOffset);
3207 }
3208 else if (match(compiler, TOKEN_FOR))
3209 {
3210 forStatement(compiler);
3211 }
3212 else if (match(compiler, TOKEN_IF))
3213 {
3214 ifStatement(compiler);
3215 }
3216 else if (match(compiler, TOKEN_RETURN))
3217 {
3218 // Compile the return value.
3219 if (peek(compiler) == TOKEN_LINE)
3220 {
3221 // If there's no expression after return, initializers should
3222 // return 'this' and regular methods should return null
3223 Code result = compiler->isInitializer ? CODE_LOAD_LOCAL_0 : CODE_NULL;
3224 emitOp(compiler, result);
3225 }
3226 else
3227 {
3228 if (compiler->isInitializer)
3229 {
3230 error(compiler, "A constructor cannot return a value.");
3231 }
3232
3233 expression(compiler);
3234 }
3235
3236 emitOp(compiler, CODE_RETURN);
3237 }
3238 else if (match(compiler, TOKEN_WHILE))
3239 {
3240 whileStatement(compiler);
3241 }
3242 else if (match(compiler, TOKEN_LEFT_BRACE))
3243 {
3244 // Block statement.
3245 pushScope(compiler);
3246 if (finishBlock(compiler))
3247 {
3248 // Block was an expression, so discard it.
3249 emitOp(compiler, CODE_POP);
3250 }
3251 popScope(compiler);
3252 }
3253 else
3254 {
3255 // Expression statement.
3256 expression(compiler);
3257 emitOp(compiler, CODE_POP);
3258 }
3259}
3260
3261// Creates a matching constructor method for an initializer with [signature]
3262// and [initializerSymbol].
3263//
3264// Construction is a two-stage process in Wren that involves two separate
3265// methods. There is a static method that allocates a new instance of the class.
3266// It then invokes an initializer method on the new instance, forwarding all of
3267// the constructor arguments to it.
3268//
3269// The allocator method always has a fixed implementation:
3270//
3271// CODE_CONSTRUCT - Replace the class in slot 0 with a new instance of it.
3272// CODE_CALL - Invoke the initializer on the new instance.
3273//
3274// This creates that method and calls the initializer with [initializerSymbol].
3275static void createConstructor(Compiler* compiler, Signature* signature,
3276 int initializerSymbol)
3277{
3278 Compiler methodCompiler;
3279 initCompiler(&methodCompiler, compiler->parser, compiler, true);
3280
3281 // Allocate the instance.
3282 emitOp(&methodCompiler, compiler->enclosingClass->isForeign
3283 ? CODE_FOREIGN_CONSTRUCT : CODE_CONSTRUCT);
3284
3285 // Run its initializer.
3286 emitShortArg(&methodCompiler, (Code)(CODE_CALL_0 + signature->arity),
3287 initializerSymbol);
3288
3289 // Return the instance.
3290 emitOp(&methodCompiler, CODE_RETURN);
3291
3292 endCompiler(&methodCompiler, "", 0);
3293}
3294
3295// Loads the enclosing class onto the stack and then binds the function already
3296// on the stack as a method on that class.
3297static void defineMethod(Compiler* compiler, Variable classVariable,
3298 bool isStatic, int methodSymbol)
3299{
3300 // Load the class. We have to do this for each method because we can't
3301 // keep the class on top of the stack. If there are static fields, they
3302 // will be locals above the initial variable slot for the class on the
3303 // stack. To skip past those, we just load the class each time right before
3304 // defining a method.
3305 loadVariable(compiler, classVariable);
3306
3307 // Define the method.
3308 Code instruction = isStatic ? CODE_METHOD_STATIC : CODE_METHOD_INSTANCE;
3309 emitShortArg(compiler, instruction, methodSymbol);
3310}
3311
3312// Declares a method in the enclosing class with [signature].
3313//
3314// Reports an error if a method with that signature is already declared.
3315// Returns the symbol for the method.
3316static int declareMethod(Compiler* compiler, Signature* signature,
3317 const char* name, int length)
3318{
3319 int symbol = signatureSymbol(compiler, signature);
3320
3321 // See if the class has already declared method with this signature.
3322 ClassInfo* classInfo = compiler->enclosingClass;
3323 IntBuffer* methods = classInfo->inStatic
3324 ? &classInfo->staticMethods : &classInfo->methods;
3325 for (int i = 0; i < methods->count; i++)
3326 {
3327 if (methods->data[i] == symbol)
3328 {
3329 const char* staticPrefix = classInfo->inStatic ? "static " : "";
3330 error(compiler, "Class %s already defines a %smethod '%s'.",
3331 &compiler->enclosingClass->name->value, staticPrefix, name);
3332 break;
3333 }
3334 }
3335
3336 wrenIntBufferWrite(compiler->parser->vm, methods, symbol);
3337 return symbol;
3338}
3339
3340static Value consumeLiteral(Compiler* compiler, const char* message)
3341{
3342 if(match(compiler, TOKEN_FALSE)) return FALSE_VAL;
3343 if(match(compiler, TOKEN_TRUE)) return TRUE_VAL;
3344 if(match(compiler, TOKEN_NUMBER)) return compiler->parser->previous.value;
3345 if(match(compiler, TOKEN_STRING)) return compiler->parser->previous.value;
3346 if(match(compiler, TOKEN_NAME)) return compiler->parser->previous.value;
3347
3348 error(compiler, message);
3349 nextToken(compiler->parser);
3350 return NULL_VAL;
3351}
3352
3353static bool matchAttribute(Compiler* compiler) {
3354
3355 if(match(compiler, TOKEN_HASH))
3356 {
3357 compiler->numAttributes++;
3358 bool runtimeAccess = match(compiler, TOKEN_BANG);
3359 if(match(compiler, TOKEN_NAME))
3360 {
3361 Value group = compiler->parser->previous.value;
3362 TokenType ahead = peek(compiler);
3363 if(ahead == TOKEN_EQ || ahead == TOKEN_LINE)
3364 {
3365 Value key = group;
3366 Value value = NULL_VAL;
3367 if(match(compiler, TOKEN_EQ))
3368 {
3369 value = consumeLiteral(compiler, "Expect a Bool, Num, String or Identifier literal for an attribute value.");
3370 }
3371 if(runtimeAccess) addToAttributeGroup(compiler, NULL_VAL, key, value);
3372 }
3373 else if(match(compiler, TOKEN_LEFT_PAREN))
3374 {
3375 ignoreNewlines(compiler);
3376 if(match(compiler, TOKEN_RIGHT_PAREN))
3377 {
3378 error(compiler, "Expected attributes in group, group cannot be empty.");
3379 }
3380 else
3381 {
3382 while(peek(compiler) != TOKEN_RIGHT_PAREN)
3383 {
3384 consume(compiler, TOKEN_NAME, "Expect name for attribute key.");
3385 Value key = compiler->parser->previous.value;
3386 Value value = NULL_VAL;
3387 if(match(compiler, TOKEN_EQ))
3388 {
3389 value = consumeLiteral(compiler, "Expect a Bool, Num, String or Identifier literal for an attribute value.");
3390 }
3391 if(runtimeAccess) addToAttributeGroup(compiler, group, key, value);
3392 ignoreNewlines(compiler);
3393 if(!match(compiler, TOKEN_COMMA)) break;
3394 ignoreNewlines(compiler);
3395 }
3396
3397 ignoreNewlines(compiler);
3398 consume(compiler, TOKEN_RIGHT_PAREN,
3399 "Expected ')' after grouped attributes.");
3400 }
3401 }
3402 else
3403 {
3404 error(compiler, "Expect an equal, newline or grouping after an attribute key.");
3405 }
3406 }
3407 else
3408 {
3409 error(compiler, "Expect an attribute definition after #.");
3410 }
3411
3412 consumeLine(compiler, "Expect newline after attribute.");
3413 return true;
3414 }
3415
3416 return false;
3417}
3418
3419// Compiles a method definition inside a class body.
3420//
3421// Returns `true` if it compiled successfully, or `false` if the method couldn't
3422// be parsed.
3423static bool method(Compiler* compiler, Variable classVariable)
3424{
3425 // Parse any attributes before the method and store them
3426 if(matchAttribute(compiler)) {
3427 return method(compiler, classVariable);
3428 }
3429
3430 // TODO: What about foreign constructors?
3431 bool isForeign = match(compiler, TOKEN_FOREIGN);
3432 bool isStatic = match(compiler, TOKEN_STATIC);
3433 compiler->enclosingClass->inStatic = isStatic;
3434
3435 SignatureFn signatureFn = rules[compiler->parser->current.type].method;
3436 nextToken(compiler->parser);
3437
3438 if (signatureFn == NULL)
3439 {
3440 error(compiler, "Expect method definition.");
3441 return false;
3442 }
3443
3444 // Build the method signature.
3445 Signature signature = signatureFromToken(compiler, SIG_GETTER);
3446 compiler->enclosingClass->signature = &signature;
3447
3448 Compiler methodCompiler;
3449 initCompiler(&methodCompiler, compiler->parser, compiler, true);
3450
3451 // Compile the method signature.
3452 signatureFn(&methodCompiler, &signature);
3453
3454 methodCompiler.isInitializer = signature.type == SIG_INITIALIZER;
3455
3456 if (isStatic && signature.type == SIG_INITIALIZER)
3457 {
3458 error(compiler, "A constructor cannot be static.");
3459 }
3460
3461 // Include the full signature in debug messages in stack traces.
3462 char fullSignature[MAX_METHOD_SIGNATURE];
3463 int length;
3464 signatureToString(&signature, fullSignature, &length);
3465
3466 // Copy any attributes the compiler collected into the enclosing class
3467 copyMethodAttributes(compiler, isForeign, isStatic, fullSignature, length);
3468
3469 // Check for duplicate methods. Doesn't matter that it's already been
3470 // defined, error will discard bytecode anyway.
3471 // Check if the method table already contains this symbol
3472 int methodSymbol = declareMethod(compiler, &signature, fullSignature, length);
3473
3474 if (isForeign)
3475 {
3476 // Define a constant for the signature.
3477 emitConstant(compiler, wrenNewStringLength(compiler->parser->vm,
3478 fullSignature, length));
3479
3480 // We don't need the function we started compiling in the parameter list
3481 // any more.
3482 methodCompiler.parser->vm->compiler = methodCompiler.parent;
3483 }
3484 else
3485 {
3486 consume(compiler, TOKEN_LEFT_BRACE, "Expect '{' to begin method body.");
3487 finishBody(&methodCompiler);
3488 endCompiler(&methodCompiler, fullSignature, length);
3489 }
3490
3491 // Define the method. For a constructor, this defines the instance
3492 // initializer method.
3493 defineMethod(compiler, classVariable, isStatic, methodSymbol);
3494
3495 if (signature.type == SIG_INITIALIZER)
3496 {
3497 // Also define a matching constructor method on the metaclass.
3498 signature.type = SIG_METHOD;
3499 int constructorSymbol = signatureSymbol(compiler, &signature);
3500
3501 createConstructor(compiler, &signature, methodSymbol);
3502 defineMethod(compiler, classVariable, true, constructorSymbol);
3503 }
3504
3505 return true;
3506}
3507
3508// Compiles a class definition. Assumes the "class" token has already been
3509// consumed (along with a possibly preceding "foreign" token).
3510static void classDefinition(Compiler* compiler, bool isForeign)
3511{
3512 // Create a variable to store the class in.
3513 Variable classVariable;
3514 classVariable.scope = compiler->scopeDepth == -1 ? SCOPE_MODULE : SCOPE_LOCAL;
3515 classVariable.index = declareNamedVariable(compiler);
3516
3517 // Create shared class name value
3518 Value classNameString = wrenNewStringLength(compiler->parser->vm,
3519 compiler->parser->previous.start, compiler->parser->previous.length);
3520
3521 // Create class name string to track method duplicates
3522 ObjString* className = AS_STRING(classNameString);
3523
3524 // Make a string constant for the name.
3525 emitConstant(compiler, classNameString);
3526
3527 // Load the superclass (if there is one).
3528 if (match(compiler, TOKEN_IS))
3529 {
3530 parsePrecedence(compiler, PREC_CALL);
3531 }
3532 else
3533 {
3534 // Implicitly inherit from Object.
3535 loadCoreVariable(compiler, "Object");
3536 }
3537
3538 // Store a placeholder for the number of fields argument. We don't know the
3539 // count until we've compiled all the methods to see which fields are used.
3540 int numFieldsInstruction = -1;
3541 if (isForeign)
3542 {
3543 emitOp(compiler, CODE_FOREIGN_CLASS);
3544 }
3545 else
3546 {
3547 numFieldsInstruction = emitByteArg(compiler, CODE_CLASS, 255);
3548 }
3549
3550 // Store it in its name.
3551 defineVariable(compiler, classVariable.index);
3552
3553 // Push a local variable scope. Static fields in a class body are hoisted out
3554 // into local variables declared in this scope. Methods that use them will
3555 // have upvalues referencing them.
3556 pushScope(compiler);
3557
3558 ClassInfo classInfo;
3559 classInfo.isForeign = isForeign;
3560 classInfo.name = className;
3561
3562 // Allocate attribute maps if necessary.
3563 // A method will allocate the methods one if needed
3564 classInfo.classAttributes = compiler->attributes->count > 0
3565 ? wrenNewMap(compiler->parser->vm)
3566 : NULL;
3567 classInfo.methodAttributes = NULL;
3568 // Copy any existing attributes into the class
3569 copyAttributes(compiler, classInfo.classAttributes);
3570
3571 // Set up a symbol table for the class's fields. We'll initially compile
3572 // them to slots starting at zero. When the method is bound to the class, the
3573 // bytecode will be adjusted by [wrenBindMethod] to take inherited fields
3574 // into account.
3575 wrenSymbolTableInit(&classInfo.fields);
3576
3577 // Set up symbol buffers to track duplicate static and instance methods.
3578 wrenIntBufferInit(&classInfo.methods);
3579 wrenIntBufferInit(&classInfo.staticMethods);
3580 compiler->enclosingClass = &classInfo;
3581
3582 // Compile the method definitions.
3583 consume(compiler, TOKEN_LEFT_BRACE, "Expect '{' after class declaration.");
3584 matchLine(compiler);
3585
3586 while (!match(compiler, TOKEN_RIGHT_BRACE))
3587 {
3588 if (!method(compiler, classVariable)) break;
3589
3590 // Don't require a newline after the last definition.
3591 if (match(compiler, TOKEN_RIGHT_BRACE)) break;
3592
3593 consumeLine(compiler, "Expect newline after definition in class.");
3594 }
3595
3596 // If any attributes are present,
3597 // instantiate a ClassAttributes instance for the class
3598 // and send it over to CODE_END_CLASS
3599 bool hasAttr = classInfo.classAttributes != NULL ||
3600 classInfo.methodAttributes != NULL;
3601 if(hasAttr) {
3602 emitClassAttributes(compiler, &classInfo);
3603 loadVariable(compiler, classVariable);
3604 // At the moment, we don't have other uses for CODE_END_CLASS,
3605 // so we put it inside this condition. Later, we can always
3606 // emit it and use it as needed.
3607 emitOp(compiler, CODE_END_CLASS);
3608 }
3609
3610 // Update the class with the number of fields.
3611 if (!isForeign)
3612 {
3613 compiler->fn->code.data[numFieldsInstruction] =
3614 (uint8_t)classInfo.fields.count;
3615 }
3616
3617 // Clear symbol tables for tracking field and method names.
3618 wrenSymbolTableClear(compiler->parser->vm, &classInfo.fields);
3619 wrenIntBufferClear(compiler->parser->vm, &classInfo.methods);
3620 wrenIntBufferClear(compiler->parser->vm, &classInfo.staticMethods);
3621 compiler->enclosingClass = NULL;
3622 popScope(compiler);
3623}
3624
3625// Compiles an "import" statement.
3626//
3627// An import compiles to a series of instructions. Given:
3628//
3629// import "foo" for Bar, Baz
3630//
3631// We compile a single IMPORT_MODULE "foo" instruction to load the module
3632// itself. When that finishes executing the imported module, it leaves the
3633// ObjModule in vm->lastModule. Then, for Bar and Baz, we:
3634//
3635// * Declare a variable in the current scope with that name.
3636// * Emit an IMPORT_VARIABLE instruction to load the variable's value from the
3637// other module.
3638// * Compile the code to store that value in the variable in this scope.
3639static void import(Compiler* compiler)
3640{
3641 ignoreNewlines(compiler);
3642 consume(compiler, TOKEN_STRING, "Expect a string after 'import'.");
3643 int moduleConstant = addConstant(compiler, compiler->parser->previous.value);
3644
3645 // Load the module.
3646 emitShortArg(compiler, CODE_IMPORT_MODULE, moduleConstant);
3647
3648 // Discard the unused result value from calling the module body's closure.
3649 emitOp(compiler, CODE_POP);
3650
3651 // The for clause is optional.
3652 if (!match(compiler, TOKEN_FOR)) return;
3653
3654 // Compile the comma-separated list of variables to import.
3655 do
3656 {
3657 ignoreNewlines(compiler);
3658
3659 consume(compiler, TOKEN_NAME, "Expect variable name.");
3660
3661 // We need to hold onto the source variable,
3662 // in order to reference it in the import later
3663 Token sourceVariableToken = compiler->parser->previous;
3664
3665 // Define a string constant for the original variable name.
3666 int sourceVariableConstant = addConstant(compiler,
3667 wrenNewStringLength(compiler->parser->vm,
3668 sourceVariableToken.start,
3669 sourceVariableToken.length));
3670
3671 // Store the symbol we care about for the variable
3672 int slot = -1;
3673 if(match(compiler, TOKEN_AS))
3674 {
3675 //import "module" for Source as Dest
3676 //Use 'Dest' as the name by declaring a new variable for it.
3677 //This parses a name after the 'as' and defines it.
3678 slot = declareNamedVariable(compiler);
3679 }
3680 else
3681 {
3682 //import "module" for Source
3683 //Uses 'Source' as the name directly
3684 slot = declareVariable(compiler, &sourceVariableToken);
3685 }
3686
3687 // Load the variable from the other module.
3688 emitShortArg(compiler, CODE_IMPORT_VARIABLE, sourceVariableConstant);
3689
3690 // Store the result in the variable here.
3691 defineVariable(compiler, slot);
3692 } while (match(compiler, TOKEN_COMMA));
3693}
3694
3695// Compiles a "var" variable definition statement.
3696static void variableDefinition(Compiler* compiler)
3697{
3698 // Grab its name, but don't declare it yet. A (local) variable shouldn't be
3699 // in scope in its own initializer.
3700 consume(compiler, TOKEN_NAME, "Expect variable name.");
3701 Token nameToken = compiler->parser->previous;
3702
3703 // Compile the initializer.
3704 if (match(compiler, TOKEN_EQ))
3705 {
3706 ignoreNewlines(compiler);
3707 expression(compiler);
3708 }
3709 else
3710 {
3711 // Default initialize it to null.
3712 null(compiler, false);
3713 }
3714
3715 // Now put it in scope.
3716 int symbol = declareVariable(compiler, &nameToken);
3717 defineVariable(compiler, symbol);
3718}
3719
3720// Compiles a "definition". These are the statements that bind new variables.
3721// They can only appear at the top level of a block and are prohibited in places
3722// like the non-curly body of an if or while.
3723void definition(Compiler* compiler)
3724{
3725 if(matchAttribute(compiler)) {
3726 definition(compiler);
3727 return;
3728 }
3729
3730 if (match(compiler, TOKEN_CLASS))
3731 {
3732 classDefinition(compiler, false);
3733 return;
3734 }
3735 else if (match(compiler, TOKEN_FOREIGN))
3736 {
3737 consume(compiler, TOKEN_CLASS, "Expect 'class' after 'foreign'.");
3738 classDefinition(compiler, true);
3739 return;
3740 }
3741
3742 disallowAttributes(compiler);
3743
3744 if (match(compiler, TOKEN_IMPORT))
3745 {
3746 import(compiler);
3747 }
3748 else if (match(compiler, TOKEN_VAR))
3749 {
3750 variableDefinition(compiler);
3751 }
3752 else
3753 {
3754 statement(compiler);
3755 }
3756}
3757
3758ObjFn* wrenCompile(WrenVM* vm, ObjModule* module, const char* source,
3759 bool isExpression, bool printErrors)
3760{
3761 // Skip the UTF-8 BOM if there is one.
3762 if (strncmp(source, "\xEF\xBB\xBF", 3) == 0) source += 3;
3763
3764 Parser parser;
3765 parser.vm = vm;
3766 parser.module = module;
3767 parser.source = source;
3768
3769 parser.tokenStart = source;
3770 parser.currentChar = source;
3771 parser.currentLine = 1;
3772 parser.numParens = 0;
3773
3774 // Zero-init the current token. This will get copied to previous when
3775 // nextToken() is called below.
3776 parser.next.type = TOKEN_ERROR;
3777 parser.next.start = source;
3778 parser.next.length = 0;
3779 parser.next.line = 0;
3780 parser.next.value = UNDEFINED_VAL;
3781
3782 parser.printErrors = printErrors;
3783 parser.hasError = false;
3784
3785 // Read the first token into next
3786 nextToken(&parser);
3787 // Copy next -> current
3788 nextToken(&parser);
3789
3790 int numExistingVariables = module->variables.count;
3791
3792 Compiler compiler;
3793 initCompiler(&compiler, &parser, NULL, false);
3794 ignoreNewlines(&compiler);
3795
3796 if (isExpression)
3797 {
3798 expression(&compiler);
3799 consume(&compiler, TOKEN_EOF, "Expect end of expression.");
3800 }
3801 else
3802 {
3803 while (!match(&compiler, TOKEN_EOF))
3804 {
3805 definition(&compiler);
3806
3807 // If there is no newline, it must be the end of file on the same line.
3808 if (!matchLine(&compiler))
3809 {
3810 consume(&compiler, TOKEN_EOF, "Expect end of file.");
3811 break;
3812 }
3813 }
3814
3815 emitOp(&compiler, CODE_END_MODULE);
3816 }
3817
3818 emitOp(&compiler, CODE_RETURN);
3819
3820 // See if there are any implicitly declared module-level variables that never
3821 // got an explicit definition. They will have values that are numbers
3822 // indicating the line where the variable was first used.
3823 for (int i = numExistingVariables; i < parser.module->variables.count; i++)
3824 {
3825 if (IS_NUM(parser.module->variables.data[i]))
3826 {
3827 // Synthesize a token for the original use site.
3828 parser.previous.type = TOKEN_NAME;
3829 parser.previous.start = parser.module->variableNames.data[i]->value;
3830 parser.previous.length = parser.module->variableNames.data[i]->length;
3831 parser.previous.line = (int)AS_NUM(parser.module->variables.data[i]);
3832 error(&compiler, "Variable is used but not defined.");
3833 }
3834 }
3835
3836 return endCompiler(&compiler, "(script)", 8);
3837}
3838
3839void wrenBindMethodCode(ObjClass* classObj, ObjFn* fn)
3840{
3841 int ip = 0;
3842 for (;;)
3843 {
3844 Code instruction = (Code)fn->code.data[ip];
3845 switch (instruction)
3846 {
3847 case CODE_LOAD_FIELD:
3848 case CODE_STORE_FIELD:
3849 case CODE_LOAD_FIELD_THIS:
3850 case CODE_STORE_FIELD_THIS:
3851 // Shift this class's fields down past the inherited ones. We don't
3852 // check for overflow here because we'll see if the number of fields
3853 // overflows when the subclass is created.
3854 fn->code.data[ip + 1] += classObj->superclass->numFields;
3855 break;
3856
3857 case CODE_SUPER_0:
3858 case CODE_SUPER_1:
3859 case CODE_SUPER_2:
3860 case CODE_SUPER_3:
3861 case CODE_SUPER_4:
3862 case CODE_SUPER_5:
3863 case CODE_SUPER_6:
3864 case CODE_SUPER_7:
3865 case CODE_SUPER_8:
3866 case CODE_SUPER_9:
3867 case CODE_SUPER_10:
3868 case CODE_SUPER_11:
3869 case CODE_SUPER_12:
3870 case CODE_SUPER_13:
3871 case CODE_SUPER_14:
3872 case CODE_SUPER_15:
3873 case CODE_SUPER_16:
3874 {
3875 // Fill in the constant slot with a reference to the superclass.
3876 int constant = (fn->code.data[ip + 3] << 8) | fn->code.data[ip + 4];
3877 fn->constants.data[constant] = OBJ_VAL(classObj->superclass);
3878 break;
3879 }
3880
3881 case CODE_CLOSURE:
3882 {
3883 // Bind the nested closure too.
3884 int constant = (fn->code.data[ip + 1] << 8) | fn->code.data[ip + 2];
3885 wrenBindMethodCode(classObj, AS_FN(fn->constants.data[constant]));
3886 break;
3887 }
3888
3889 case CODE_END:
3890 return;
3891
3892 default:
3893 // Other instructions are unaffected, so just skip over them.
3894 break;
3895 }
3896 ip += 1 + getByteCountForArguments(fn->code.data, fn->constants.data, ip);
3897 }
3898}
3899
3900void wrenMarkCompiler(WrenVM* vm, Compiler* compiler)
3901{
3902 wrenGrayValue(vm, compiler->parser->current.value);
3903 wrenGrayValue(vm, compiler->parser->previous.value);
3904 wrenGrayValue(vm, compiler->parser->next.value);
3905
3906 // Walk up the parent chain to mark the outer compilers too. The VM only
3907 // tracks the innermost one.
3908 do
3909 {
3910 wrenGrayObj(vm, (Obj*)compiler->fn);
3911 wrenGrayObj(vm, (Obj*)compiler->constants);
3912 wrenGrayObj(vm, (Obj*)compiler->attributes);
3913
3914 if (compiler->enclosingClass != NULL)
3915 {
3916 wrenBlackenSymbolTable(vm, &compiler->enclosingClass->fields);
3917
3918 if(compiler->enclosingClass->methodAttributes != NULL)
3919 {
3920 wrenGrayObj(vm, (Obj*)compiler->enclosingClass->methodAttributes);
3921 }
3922 if(compiler->enclosingClass->classAttributes != NULL)
3923 {
3924 wrenGrayObj(vm, (Obj*)compiler->enclosingClass->classAttributes);
3925 }
3926 }
3927
3928 compiler = compiler->parent;
3929 }
3930 while (compiler != NULL);
3931}
3932
3933// Helpers for Attributes
3934
3935// Throw an error if any attributes were found preceding,
3936// and clear the attributes so the error doesn't keep happening.
3937static void disallowAttributes(Compiler* compiler)
3938{
3939 if (compiler->numAttributes > 0)
3940 {
3941 error(compiler, "Attributes can only specified before a class or a method");
3942 wrenMapClear(compiler->parser->vm, compiler->attributes);
3943 compiler->numAttributes = 0;
3944 }
3945}
3946
3947// Add an attribute to a given group in the compiler attribues map
3948static void addToAttributeGroup(Compiler* compiler,
3949 Value group, Value key, Value value)
3950{
3951 WrenVM* vm = compiler->parser->vm;
3952
3953 if(IS_OBJ(group)) wrenPushRoot(vm, AS_OBJ(group));
3954 if(IS_OBJ(key)) wrenPushRoot(vm, AS_OBJ(key));
3955 if(IS_OBJ(value)) wrenPushRoot(vm, AS_OBJ(value));
3956
3957 Value groupMapValue = wrenMapGet(compiler->attributes, group);
3958 if(IS_UNDEFINED(groupMapValue))
3959 {
3960 groupMapValue = OBJ_VAL(wrenNewMap(vm));
3961 wrenMapSet(vm, compiler->attributes, group, groupMapValue);
3962 }
3963
3964 //we store them as a map per so we can maintain duplicate keys
3965 //group = { key:[value, ...], }
3966 ObjMap* groupMap = AS_MAP(groupMapValue);
3967
3968 //var keyItems = group[key]
3969 //if(!keyItems) keyItems = group[key] = []
3970 Value keyItemsValue = wrenMapGet(groupMap, key);
3971 if(IS_UNDEFINED(keyItemsValue))
3972 {
3973 keyItemsValue = OBJ_VAL(wrenNewList(vm, 0));
3974 wrenMapSet(vm, groupMap, key, keyItemsValue);
3975 }
3976
3977 //keyItems.add(value)
3978 ObjList* keyItems = AS_LIST(keyItemsValue);
3979 wrenValueBufferWrite(vm, &keyItems->elements, value);
3980
3981 if(IS_OBJ(group)) wrenPopRoot(vm);
3982 if(IS_OBJ(key)) wrenPopRoot(vm);
3983 if(IS_OBJ(value)) wrenPopRoot(vm);
3984}
3985
3986
3987// Emit the attributes in the give map onto the stack
3988static void emitAttributes(Compiler* compiler, ObjMap* attributes)
3989{
3990 // Instantiate a new map for the attributes
3991 loadCoreVariable(compiler, "Map");
3992 callMethod(compiler, 0, "new()", 5);
3993
3994 // The attributes are stored as group = { key:[value, value, ...] }
3995 // so our first level is the group map
3996 for(uint32_t groupIdx = 0; groupIdx < attributes->capacity; groupIdx++)
3997 {
3998 const MapEntry* groupEntry = &attributes->entries[groupIdx];
3999 if(IS_UNDEFINED(groupEntry->key)) continue;
4000 //group key
4001 emitConstant(compiler, groupEntry->key);
4002
4003 //group value is gonna be a map
4004 loadCoreVariable(compiler, "Map");
4005 callMethod(compiler, 0, "new()", 5);
4006
4007 ObjMap* groupItems = AS_MAP(groupEntry->value);
4008 for(uint32_t itemIdx = 0; itemIdx < groupItems->capacity; itemIdx++)
4009 {
4010 const MapEntry* itemEntry = &groupItems->entries[itemIdx];
4011 if(IS_UNDEFINED(itemEntry->key)) continue;
4012
4013 emitConstant(compiler, itemEntry->key);
4014 // Attribute key value, key = []
4015 loadCoreVariable(compiler, "List");
4016 callMethod(compiler, 0, "new()", 5);
4017 // Add the items to the key list
4018 ObjList* items = AS_LIST(itemEntry->value);
4019 for(int itemIdx = 0; itemIdx < items->elements.count; ++itemIdx)
4020 {
4021 emitConstant(compiler, items->elements.data[itemIdx]);
4022 callMethod(compiler, 1, "addCore_(_)", 11);
4023 }
4024 // Add the list to the map
4025 callMethod(compiler, 2, "addCore_(_,_)", 13);
4026 }
4027
4028 // Add the key/value to the map
4029 callMethod(compiler, 2, "addCore_(_,_)", 13);
4030 }
4031
4032}
4033
4034// Methods are stored as method <-> attributes, so we have to have
4035// an indirection to resolve for methods
4036static void emitAttributeMethods(Compiler* compiler, ObjMap* attributes)
4037{
4038 // Instantiate a new map for the attributes
4039 loadCoreVariable(compiler, "Map");
4040 callMethod(compiler, 0, "new()", 5);
4041
4042 for(uint32_t methodIdx = 0; methodIdx < attributes->capacity; methodIdx++)
4043 {
4044 const MapEntry* methodEntry = &attributes->entries[methodIdx];
4045 if(IS_UNDEFINED(methodEntry->key)) continue;
4046 emitConstant(compiler, methodEntry->key);
4047 ObjMap* attributeMap = AS_MAP(methodEntry->value);
4048 emitAttributes(compiler, attributeMap);
4049 callMethod(compiler, 2, "addCore_(_,_)", 13);
4050 }
4051}
4052
4053
4054// Emit the final ClassAttributes that exists at runtime
4055static void emitClassAttributes(Compiler* compiler, ClassInfo* classInfo)
4056{
4057 loadCoreVariable(compiler, "ClassAttributes");
4058
4059 classInfo->classAttributes
4060 ? emitAttributes(compiler, classInfo->classAttributes)
4061 : null(compiler, false);
4062
4063 classInfo->methodAttributes
4064 ? emitAttributeMethods(compiler, classInfo->methodAttributes)
4065 : null(compiler, false);
4066
4067 callMethod(compiler, 2, "new(_,_)", 8);
4068}
4069
4070// Copy the current attributes stored in the compiler into a destination map
4071// This also resets the counter, since the intent is to consume the attributes
4072static void copyAttributes(Compiler* compiler, ObjMap* into)
4073{
4074 compiler->numAttributes = 0;
4075
4076 if(compiler->attributes->count == 0) return;
4077 if(into == NULL) return;
4078
4079 WrenVM* vm = compiler->parser->vm;
4080
4081 // Note we copy the actual values as is since we'll take ownership
4082 // and clear the original map
4083 for(uint32_t attrIdx = 0; attrIdx < compiler->attributes->capacity; attrIdx++)
4084 {
4085 const MapEntry* attrEntry = &compiler->attributes->entries[attrIdx];
4086 if(IS_UNDEFINED(attrEntry->key)) continue;
4087 wrenMapSet(vm, into, attrEntry->key, attrEntry->value);
4088 }
4089
4090 wrenMapClear(vm, compiler->attributes);
4091}
4092
4093// Copy the current attributes stored in the compiler into the method specific
4094// attributes for the current enclosingClass.
4095// This also resets the counter, since the intent is to consume the attributes
4096static void copyMethodAttributes(Compiler* compiler, bool isForeign,
4097 bool isStatic, const char* fullSignature, int32_t length)
4098{
4099 compiler->numAttributes = 0;
4100
4101 if(compiler->attributes->count == 0) return;
4102
4103 WrenVM* vm = compiler->parser->vm;
4104
4105 // Make a map for this method to copy into
4106 ObjMap* methodAttr = wrenNewMap(vm);
4107 wrenPushRoot(vm, (Obj*)methodAttr);
4108 copyAttributes(compiler, methodAttr);
4109
4110 // Include 'foreign static ' in front as needed
4111 int32_t fullLength = length;
4112 if(isForeign) fullLength += 8;
4113 if(isStatic) fullLength += 7;
4114 char fullSignatureWithPrefix[MAX_METHOD_SIGNATURE + 8 + 7];
4115 const char* foreignPrefix = isForeign ? "foreign " : "";
4116 const char* staticPrefix = isStatic ? "static " : "";
4117 sprintf(fullSignatureWithPrefix, "%s%s%.*s", foreignPrefix, staticPrefix,
4118 length, fullSignature);
4119 fullSignatureWithPrefix[fullLength] = '\0';
4120
4121 if(compiler->enclosingClass->methodAttributes == NULL) {
4122 compiler->enclosingClass->methodAttributes = wrenNewMap(vm);
4123 }
4124
4125 // Store the method attributes in the class map
4126 Value key = wrenNewStringLength(vm, fullSignatureWithPrefix, fullLength);
4127 wrenMapSet(vm, compiler->enclosingClass->methodAttributes, key, OBJ_VAL(methodAttr));
4128
4129 wrenPopRoot(vm);
4130}
4131