| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022 |
- /**
- ******************************************************************************
- * @file : compiler.c
- * @author : simon
- * @brief : None
- * @attention : None
- * @date : 2023/8/17
- ******************************************************************************
- */
- #include "compiler.h"
- #include "common.h"
- #include "scanner.h"
- #ifdef DEBUG_PRINT_CODE
- #include "debug.h"
- #endif
- #include "memory.h"
- typedef struct {
- Token current;
- Token previous;
- bool hadError;
- bool panicMode;
- } Parser;
- typedef enum {
- PREC_NONE,
- PREC_ASSIGNMENT,// =
- PREC_OR, // or
- PREC_AND, // and
- PREC_EQUALITY, // == !=
- PREC_COMPARISON,// < > <= >=
- PREC_TERM, // + -
- PREC_FACTOR, // * /
- PREC_UNARY, // ! -
- PREC_CALL, // . ()
- PREC_PRIMARY
- } Precedence;
- typedef void (*ParseFn)(bool canAssign);
- typedef struct {
- ParseFn prefix;
- ParseFn infix;
- Precedence precedence;
- } ParseRule;
- typedef struct {
- Token name;
- int depth;
- bool isCaptured;
- } Local;
- typedef struct {
- uint8_t index;
- bool isLocal;
- } Upvalue;
- typedef enum {
- TYPE_METHOD,
- TYPE_FUNCTION,
- TYPE_INITIALIZER,
- TYPE_SCRIPT,
- } FunctionType;
- typedef struct Compiler {
- struct Compiler *enclosing;
- ObjFunction *function;
- FunctionType type;
- Local locals[UINT8_COUNT];
- int localCount;/// how many locals are in scope
- Upvalue upvalues[UINT8_COUNT];
- int scopeDepth;
- } Compiler;
- typedef struct ClassCompiler {
- struct ClassCompiler *enclosing;
- bool hasSuperclass;
- } ClassCompiler;
- Parser parser;
- Compiler *current = NULL;
- ClassCompiler *currentClass = NULL;
- static void parsePrecedence(Precedence);
- static uint8_t parseVariable(const char *);
- static void declareVariable();
- static void defineVariable(uint8_t);
- static uint8_t identifierConstant(Token *name);
- static bool identifiersEqual(Token *a, Token *b);
- static ParseRule *getRule(TokenType);
- static void statement();
- static void declaration();
- static void markInitialized();
- static void namedVariable(Token name, bool canAssign);
- static void addLocal(Token name);
- static void initCompiler(Compiler *compiler, FunctionType type);
- static void beginScope();
- static void endScope();
- static void block();
- static ObjFunction *endCompiler();
- static void variable(bool);
- static uint8_t argumentList();
- static Chunk *currentChunk() {
- return ¤t->function->chunk;
- }
- static void errorAt(Token *token, const char *message) {
- if (parser.panicMode) return;
- parser.panicMode = true;
- fprintf(stderr, "[line %d] Error", token->line);
- if (token->type == TOKEN_EOF) {
- fprintf(stderr, " at end");
- } else if (token->type == TOKEN_ERROR) {
- ///! Nothing.
- } else {
- fprintf(stderr, " at '%.*s'", token->length, token->start);
- }
- fprintf(stderr, ": %s\n", message);
- parser.hadError = true;
- }
- static void error(const char *message) {
- errorAt(&parser.previous, message);
- }
- static void errorAtCurrent(const char *message) {
- errorAt(&parser.current, message);
- }
- static void advance() {
- parser.previous = parser.current;
- for (;;) {
- parser.current = scanToken();
- if (parser.current.type != TOKEN_ERROR) break;
- errorAtCurrent(parser.current.start);
- }
- }
- void consume(TokenType type, const char *message) {
- if (parser.current.type == type) {
- advance();
- return;
- }
- errorAtCurrent(message);
- }
- static bool check(TokenType type) {
- return parser.current.type == type;
- }
- static bool match(TokenType type) {
- if (!check(type)) return false;
- advance();
- return true;
- }
- static void emitByte(uint8_t byte) {
- writeChunk(currentChunk(), byte, parser.previous.line);
- }
- static void emitBytes(uint8_t byte1, uint8_t byte2) {
- emitByte(byte1);
- emitByte(byte2);
- }
- static void emitLoop(int loopStart) {
- emitByte(OP_LOOP);
- int offset = currentChunk()->count - loopStart + 2;
- if (offset > UINT16_MAX) error("Loop body too large.");
- emitByte((offset >> 8) & 0xFF);
- emitByte(offset & 0xFF);
- }
- static int emitJump(uint8_t instruction) {
- emitByte(instruction);
- emitByte(0xff);// 占位字节,后面填入需要跳转的 offset
- emitByte(0xff);//
- return currentChunk()->count - 2;
- }
- static void emitReturn() {
- if (current->type == TYPE_INITIALIZER) {
- emitBytes(OP_GET_LOCAL, 0);
- } else {
- emitByte(OP_NIL);
- }
- emitByte(OP_RETURN);
- }
- static uint8_t makeConstant(Value value) {
- int constant = addConstant(currentChunk(), value);
- if (constant > UINT8_MAX) {
- error("Too many constants in one chunk.");
- return 0;
- }
- return (uint8_t) constant;
- }
- static void expression() {
- parsePrecedence(PREC_ASSIGNMENT);
- }
- static void function(FunctionType type) {
- Compiler compiler;
- initCompiler(&compiler, type);
- beginScope();
- consume(TOKEN_LEFT_PAREN, "Expect '(' after function name.");
- ///! Parameters
- if (!check(TOKEN_RIGHT_PAREN)) {
- do {
- current->function->arity++;
- if (current->function->arity > 255) {
- errorAtCurrent("Can't have more than 255 parameters.");
- }
- uint8_t constant = parseVariable("Expect parameter name.");
- defineVariable(constant);
- } while (match(TOKEN_COMMA));
- }
- consume(TOKEN_RIGHT_PAREN, "Expect ')' after parameters.");
- consume(TOKEN_LEFT_BRACE, "Expect '{' before function body.");
- ///! Body
- block();
- ObjFunction *fun = endCompiler();
- emitBytes(OP_CLOSURE, makeConstant(OBJ_VAL(fun)));
- for (int i = 0; i < fun->upvalueCount; i++) {
- emitByte(compiler.upvalues[i].isLocal ? 1 : 0);
- emitByte(compiler.upvalues[i].index);
- }
- //! NOTE:
- //! this beginScope() doesn't have a corresponding endScope() call.
- //! Because we end Compiler completely when we reach the end of the
- //! function body, there's no need to close the lingering outermost
- //! scope.
- }
- static void method() {
- //! To define a new method, the VM needs three things:
- //!
- //! 1. The name of the method.
- //!
- //! 2. The closure for the method body.
- //!
- //! 3. The class to bind the method to.
- consume(TOKEN_IDENTIFIER, "Expect method name.");
- uint8_t constant = identifierConstant(&parser.previous);
- // Method Body ObjClosure <OP_CLOSURE>
- FunctionType type = TYPE_METHOD;
- if (parser.previous.length == 4 && memcmp(parser.previous.start, "init", 4) == 0) {
- type = TYPE_INITIALIZER;
- }
- function(type);
- emitBytes(OP_METHOD, constant);
- }
- static Token syntheticToken(const char *text) {
- Token token;
- token.start = text;
- token.length = (int) strlen(text);
- return token;
- }
- static void classDeclaration() {
- consume(TOKEN_IDENTIFIER, "Expect class name.");
- Token className = parser.previous;
- uint8_t nameConstant = identifierConstant(&parser.previous);
- declareVariable();
- emitBytes(OP_CLASS, nameConstant);
- defineVariable(nameConstant);
- ClassCompiler classCompiler;
- classCompiler.enclosing = currentClass;
- classCompiler.hasSuperclass = false;
- currentClass = &classCompiler;
- // Superclass
- if (match(TOKEN_LESS)) {
- consume(TOKEN_IDENTIFIER, "Expect superclass name.");
- variable(false);
- if (identifiersEqual(&className, &parser.previous)) {
- error("A class can't inherit from itself.");
- }
- beginScope();
- addLocal(syntheticToken("super"));
- defineVariable(0);
- namedVariable(className, false);
- emitByte(OP_INHERIT);
- classCompiler.hasSuperclass = true;
- }
- namedVariable(className, false);
- consume(TOKEN_LEFT_BRACE, "Expect '{' before class body.");
- while (!check(TOKEN_RIGHT_BRACE) && !check(TOKEN_EOF)) {
- method();
- }
- consume(TOKEN_RIGHT_BRACE, "Expect '}' after class body.");
- emitByte(OP_POP);
- if (classCompiler.hasSuperclass) {
- endScope();
- }
- currentClass = currentClass->enclosing;
- }
- static void funDeclaration() {
- uint8_t global = parseVariable("Expect function name.");
- markInitialized();
- function(TYPE_FUNCTION);
- defineVariable(global);
- }
- /// for example: var a; var b = 10;
- static void varDeclaration() {
- uint8_t global = parseVariable("Expect variable name.");
- // 变量初始化
- if (match(TOKEN_EQUAL)) {
- expression();
- } else {
- emitByte(OP_NIL);
- }
- consume(TOKEN_SEMICOLON, "Expect ';' after variable declaration.");
- defineVariable(global);
- }
- static void expressionStatement() {
- expression();
- consume(TOKEN_SEMICOLON, "Expect ';' after expression.");
- emitByte(OP_POP);
- }
- static void patchJump(int offset) {
- // -2 to adjust for the bytecode for the jump offset itself.
- int jump = currentChunk()->count - offset - 2;
- if (jump > UINT16_MAX) error("Too much code to jump over.");
- currentChunk()->code[offset] = (jump >> 8) & 0xFF;
- currentChunk()->code[offset + 1] = jump & 0xFF;
- }
- static void forStatement() {
- /**
- * *********************************************************
- * initializer clause
- * L4: condition expression
- * OP_JUMP_IF_FALSE L1
- * OP_POP
- * OP_JUMP L3
- * L2: increment expression
- * OP_POP
- * OP_LOOP L4
- * L3: body statement
- * OP_LOOP L2
- * L1: OP_POP
- * continues...
- * *********************************************************
- */
- beginScope();
- // for(I;II;III)
- consume(TOKEN_LEFT_PAREN, "Expect '(' after 'for'.");
- ///! I.<<Initializer Part>>
- if (match(TOKEN_SEMICOLON)) {
- // No initializer.
- } else if (match(TOKEN_VAR)) {
- varDeclaration();
- } else {
- expressionStatement();// ; op_pop
- }
- ///! II.<<Condition Part>>
- int loopStart = currentChunk()->count;
- int exitJump = -1;
- if (!match(TOKEN_SEMICOLON)) {
- expression();
- consume(TOKEN_SEMICOLON, "Expect ';' after loop conditon. ");
- // Jump out of the loop if the condition is false.
- exitJump = emitJump(OP_JUMP_IF_FALSE);
- emitByte(OP_POP);
- }
- ///! III.<<Increment Clause>>
- if (!match(TOKEN_RIGHT_PAREN)) {
- int bodyJump = emitJump(OP_JUMP);
- int incrementStart = currentChunk()->count;
- expression();
- emitByte(OP_POP);
- consume(TOKEN_RIGHT_PAREN, "Expect ')' after for clauses.");
- emitLoop(loopStart);
- loopStart = incrementStart;
- patchJump(bodyJump);
- }
- ///! <<Body Part>>
- statement();
- emitLoop(loopStart);
- if (exitJump != -1) {
- patchJump(exitJump);
- emitByte(OP_POP);// Condition.
- }
- endScope();
- }
- static void returnStatement() {
- if (current->type == TYPE_SCRIPT) {
- error("Can't return from top-level code.");
- }
- if (match(TOKEN_SEMICOLON)) {
- emitReturn();
- } else {
- if (current->type == TYPE_INITIALIZER) {
- error("Can't return a value from an initializer.");
- }
- expression();
- consume(TOKEN_SEMICOLON, "Expect ';' after return value.");
- emitByte(OP_RETURN);
- }
- }
- static void ifStatement() {
- consume(TOKEN_LEFT_PAREN, "Expect '(' after 'if'.");
- expression();
- consume(TOKEN_RIGHT_PAREN, "Expect ')' after condition.");
- int thenJump = emitJump(OP_JUMP_IF_FALSE);
- emitByte(OP_POP);
- statement();// then branch statement
- int elseJump = emitJump(OP_JUMP);
- patchJump(thenJump);
- emitByte(OP_POP);
- if (match(TOKEN_ELSE)) statement();// else branch statement
- patchJump(elseJump);
- }
- static void whileStatement() {
- int loopStart = currentChunk()->count;
- consume(TOKEN_LEFT_PAREN, "Expect '(' after 'while'.");
- expression();// while condition.
- consume(TOKEN_RIGHT_PAREN, "Expect ')' after condition.");
- int exitJump = emitJump(OP_JUMP_IF_FALSE);
- emitByte(OP_POP);
- statement();// while body.
- emitLoop(loopStart);
- patchJump(exitJump);
- emitByte(OP_POP);
- }
- static void printStatement() {
- expression();
- consume(TOKEN_SEMICOLON, "Expect ';' after value.");
- emitByte(OP_PRINT);
- }
- static void synchronize() {
- parser.panicMode = false;
- while (parser.current.type != TOKEN_EOF) {
- if (parser.previous.type == TOKEN_SEMICOLON) return;
- switch (parser.current.type) {
- case TOKEN_CLASS:
- case TOKEN_FUN:
- case TOKEN_VAR:
- case TOKEN_FOR:
- case TOKEN_IF:
- case TOKEN_WHILE:
- case TOKEN_PRINT:
- case TOKEN_RETURN:
- return;
- default:;// Do nothing.
- }
- advance();
- }
- }
- ///declaration → classDecl
- /// | funDecl
- /// | varDecl
- /// | statement ;
- static void declaration() {
- if (match(TOKEN_CLASS)) {
- classDeclaration();
- } else if (match(TOKEN_FUN)) {
- funDeclaration();
- } else if (match(TOKEN_VAR)) {
- varDeclaration();
- } else {
- statement();
- }
- if (parser.panicMode) synchronize();
- }
- static void block() {
- while (!check(TOKEN_RIGHT_BRACE) && !check(TOKEN_EOF)) {
- declaration();
- }
- consume(TOKEN_RIGHT_BRACE, "Expect '}' after block.");
- }
- ///statement → exprStmt
- /// | forStmt
- /// | ifStmt
- /// | printStmt
- /// | returnStmt
- /// | whileStmt
- /// | block ;
- static void statement() {
- if (match(TOKEN_PRINT)) {
- printStatement();
- } else if (match(TOKEN_FOR)) {
- forStatement();
- } else if (match(TOKEN_IF)) {
- ifStatement();
- } else if (match(TOKEN_RETURN)) {
- returnStatement();
- } else if (match(TOKEN_WHILE)) {
- whileStatement();
- } else if (match(TOKEN_LEFT_BRACE)) {
- ///! block → "{" declaration* "}" ;
- beginScope();
- block();
- endScope();
- } else {
- expressionStatement();
- }
- }
- static void beginScope() {
- current->scopeDepth++;
- }
- static void endScope() {
- current->scopeDepth--;
- while (current->localCount > 0
- && current->locals[current->localCount - 1].depth > current->scopeDepth) {
- if (current->locals[current->localCount - 1].isCaptured) {
- emitByte(OP_CLOSE_UPVALUE);
- } else {
- emitByte(OP_POP);
- }
- current->localCount--;
- }
- }
- static void emitConstant(Value value) {
- emitBytes(OP_CONSTANT, makeConstant(value));
- }
- static void initCompiler(Compiler *compiler, FunctionType type) {
- compiler->enclosing = current;// 上一极的 compiler
- compiler->function = NULL;
- compiler->type = type;
- compiler->localCount = 0;
- compiler->scopeDepth = 0;
- compiler->function = newFunction();
- current = compiler;
- if (type != TYPE_SCRIPT) {
- ///! Function name
- current->function->name = copyString(parser.previous.start, parser.previous.length);
- }
- Local *local = ¤t->locals[current->localCount++];
- local->depth = 0;
- local->isCaptured = false;
- if (type != TYPE_FUNCTION) {
- local->name.start = "this";
- local->name.length = 4;
- } else {
- local->name.start = "";
- local->name.length = 0;
- }
- }
- static ObjFunction *endCompiler() {
- emitReturn();
- ObjFunction *function = current->function;
- #ifdef DEBUG_PRINT_CODE
- if (!parser.hadError) {
- disassembleChunk(currentChunk(), function->name != NULL ? function->name->chars : "<script>");
- }
- #endif
- current = current->enclosing;// 当前的 compiler 变成上级 compiler
- return function;
- }
- static void grouping(__attribute__((unused)) bool canAssign) {
- expression();
- consume(TOKEN_RIGHT_PAREN, "Expect ')' after expression.");
- }
- /// \brief parse number token
- /// Number literals: 123
- static void number(__attribute__((unused)) bool canAssign) {
- double value = strtod(parser.previous.start, NULL);
- emitConstant(NUMBER_VAL(value));
- }
- static void string(__attribute__((unused)) bool canAssign) {
- emitConstant(OBJ_VAL(copyString(parser.previous.start + 1,
- parser.previous.length - 2)));
- }
- static void and_(__attribute__((unused)) bool canAssign) {
- /// left operand expression
- /// OP_JUMP_IF_FALSE b
- /// OP_POP
- /// right operand expression
- /// b: continues...
- int endJump = emitJump(OP_JUMP_IF_FALSE);
- emitByte(OP_POP);
- parsePrecedence(PREC_AND);// right operand expression
- patchJump(endJump);
- }
- static void or_(__attribute__((unused)) bool canAssign) {
- /// left operand expression
- /// OP_JUMP_IF_FALSE b1
- /// OP_JUMP b2
- /// b1: OP_POP
- /// right operand expression
- /// b2: continue
- int elseJump = emitJump(OP_JUMP_IF_FALSE);
- int endJump = emitJump(OP_JUMP);
- patchJump(elseJump);
- emitByte(OP_POP);
- parsePrecedence(PREC_OR);// right operand expression
- patchJump(endJump);
- }
- static int resolveLocal(Compiler *compile, Token *name) {
- for (int i = compile->localCount - 1; i >= 0; i--) {
- Local *local = &compile->locals[i];
- if (identifiersEqual(name, &local->name)) {
- if (local->depth == -1) {
- error("Can't read local variable in ints own initializer.");
- }
- return i;
- }
- }
- return -1;
- }
- static int addUpvalue(Compiler *compiler, uint8_t index, bool isLocal) {
- int upvalueCount = compiler->function->upvalueCount;
- //! before we add a new upvalue,
- //! we first check to see if the function already has an upvalue
- //! that closes over that variable.
- for (int i = 0; i < upvalueCount; i++) {
- Upvalue *upvalue = &compiler->upvalues[i];
- if (upvalue->index == index && upvalue->isLocal == isLocal) {
- return i;
- }
- }
- if (upvalueCount == UINT8_COUNT) {
- error("Too many closure variable in function.");
- return 0;
- }
- compiler->upvalues[upvalueCount].isLocal = isLocal;
- compiler->upvalues[upvalueCount].index = index;
- return compiler->function->upvalueCount++;
- }
- static int resolveUpvalue(Compiler *compiler, Token *name) {
- if (compiler->enclosing == NULL) return -1;
- int local = resolveLocal(compiler->enclosing, name);
- if (local != -1) {
- compiler->enclosing->locals[local].isCaptured = true;
- return addUpvalue(compiler, (uint8_t) local, true);
- }
- // 递归
- int upvalue = resolveUpvalue(compiler->enclosing, name);
- if (upvalue != -1) {
- return addUpvalue(compiler, (uint8_t) upvalue, false);
- }
- return -1;
- }
- static void namedVariable(Token name, bool canAssign) {
- uint8_t getOp, setOp;
- int arg = resolveLocal(current, &name);
- if (arg != -1) {
- getOp = OP_GET_LOCAL;
- setOp = OP_SET_LOCAL;
- } else if ((arg = resolveUpvalue(current, &name)) != -1) {
- getOp = OP_GET_UPVALUE;
- setOp = OP_SET_UPVALUE;
- } else {
- arg = identifierConstant(&name);
- getOp = OP_GET_GLOBAL;
- setOp = OP_SET_GLOBAL;
- }
- if (canAssign && match(TOKEN_EQUAL)) {
- // 如 menu.brunch(sunday).beverage = "mimosa";
- expression();
- emitBytes(setOp, (uint8_t) arg);
- } else {
- emitBytes(getOp, (uint8_t) arg);
- }
- }
- static void variable(bool canAssign) {
- namedVariable(parser.previous, canAssign);
- }
- static void super_(__attribute__((unused)) bool canAssign) {
- if (currentClass == NULL) {
- error("Can't use 'super' outside of a class.");
- } else if (!currentClass->hasSuperclass) {
- error("Can't use 'super' in a class with no superclass.");
- }
- consume(TOKEN_DOT, "Expect '.' after 'super'.");
- consume(TOKEN_IDENTIFIER, "Expect superclass method name.");
- uint8_t name = identifierConstant(&parser.previous);
- namedVariable(syntheticToken("this"), false);
- if (match(TOKEN_LEFT_PAREN)) {
- uint8_t argCount = argumentList();
- namedVariable(syntheticToken("super"), false);
- emitBytes(OP_SUPER_INVOKE, name);
- emitByte(argCount);
- } else {
- namedVariable(syntheticToken("super"), false);
- emitBytes(OP_GET_SUPER, name);
- }
- }
- static void this_(__attribute__((unused)) bool canAssign) {
- if (currentClass == NULL) {
- error("Can't use 'this' outside of a class.");
- return;
- }
- variable(false);
- }
- /// Unary negation: -123
- static void unary(__attribute__((unused)) bool canAssign) {
- TokenType operatorType = parser.previous.type;
- // Compile the operand.
- parsePrecedence(PREC_UNARY);
- // Emit the operator instruction.
- switch (operatorType) {
- case TOKEN_BANG:
- emitByte(OP_NOT);
- break;
- case TOKEN_MINUS:
- emitByte(OP_NEGATE);
- break;
- default: return;// Unreachable.
- }
- }
- /// \brief infix parser
- static void binary(__attribute__((unused)) bool canAssign) {
- TokenType operatorType = parser.previous.type;
- ParseRule *rule = getRule(operatorType);
- parsePrecedence((Precedence) rule->precedence + 1);
- switch (operatorType) {
- case TOKEN_BANG_EQUAL:
- emitBytes(OP_EQUAL, OP_NOT);
- break;
- case TOKEN_EQUAL_EQUAL:
- emitByte(OP_EQUAL);
- break;
- case TOKEN_GREATER:
- emitByte(OP_GREATER);
- break;
- case TOKEN_GREATER_EQUAL:
- emitBytes(OP_LESS, OP_NOT);
- break;
- case TOKEN_LESS:
- emitByte(OP_LESS);
- break;
- case TOKEN_LESS_EQUAL:
- emitBytes(OP_GREATER, OP_NOT);
- break;
- case TOKEN_PLUS:
- emitByte(OP_ADD);
- break;
- case TOKEN_MINUS:
- emitByte(OP_SUBTRACT);
- break;
- case TOKEN_STAR:
- emitByte(OP_MULTIPLY);
- break;
- case TOKEN_SLASH:
- emitByte(OP_DIVIDE);
- break;
- default: return;// Unreachable.
- }
- }
- static uint8_t argumentList() {
- uint8_t argCount = 0;
- if (!check(TOKEN_RIGHT_PAREN)) {
- do {
- expression();
- if (argCount == 255) error("Can't have more than 255 arguments.");
- argCount++;
- } while (match(TOKEN_COMMA));
- }
- consume(TOKEN_RIGHT_PAREN, "Expect ')' after arguments.");
- return argCount;
- }
- /// Function call expression is kind of an infix ( operator.
- /// You have a high-precedence expression on the left for the thing
- /// being called - usually just a single identifier.
- /// Then the ( in the middle, followed by the argument expressions
- /// separated by commas, and a final ) to wrap it up at the end.
- static void call(__attribute__((unused)) bool canAssign) {
- uint8_t argCount = argumentList();
- emitBytes(OP_CALL, argCount);
- }
- static void literal(__attribute__((unused)) bool canAssign) {
- switch (parser.previous.type) {
- case TOKEN_FALSE:
- emitByte(OP_FALSE);
- break;
- case TOKEN_NIL:
- emitByte(OP_NIL);
- break;
- case TOKEN_TRUE:
- emitByte(OP_TRUE);
- break;
- default: return;// Unreachable
- }
- }
- static void dot(bool canAssign) {
- // eclair.filling = "pastry creme";
- consume(TOKEN_IDENTIFIER, "Expect property name after '.'.");
- uint8_t name = identifierConstant(&parser.previous);
- if (canAssign && match(TOKEN_EQUAL)) {
- expression();
- emitBytes(OP_SET_PROPERTY, name);
- } else if (match(TOKEN_LEFT_PAREN)) {
- // Instance.method()
- uint8_t argCount = argumentList();
- emitBytes(OP_INVOKE, name);
- emitByte(argCount);
- } else {
- emitBytes(OP_GET_PROPERTY, name);
- }
- }
- ParseRule rules[] = {
- [TOKEN_LEFT_PAREN] = {grouping, call, PREC_CALL},
- [TOKEN_RIGHT_PAREN] = {NULL, NULL, PREC_NONE},
- [TOKEN_LEFT_BRACE] = {NULL, NULL, PREC_NONE},
- [TOKEN_RIGHT_BRACE] = {NULL, NULL, PREC_NONE},
- [TOKEN_COMMA] = {NULL, NULL, PREC_NONE},
- [TOKEN_DOT] = {NULL, dot, PREC_CALL},
- [TOKEN_MINUS] = {unary, binary, PREC_TERM},
- [TOKEN_PLUS] = {NULL, binary, PREC_TERM},
- [TOKEN_SEMICOLON] = {NULL, NULL, PREC_NONE},
- [TOKEN_SLASH] = {NULL, binary, PREC_FACTOR},
- [TOKEN_STAR] = {NULL, binary, PREC_FACTOR},
- [TOKEN_BANG] = {unary, NULL, PREC_NONE},
- [TOKEN_BANG_EQUAL] = {NULL, binary, PREC_EQUALITY},
- [TOKEN_EQUAL] = {NULL, NULL, PREC_NONE},
- [TOKEN_EQUAL_EQUAL] = {NULL, binary, PREC_EQUALITY},
- [TOKEN_GREATER] = {NULL, binary, PREC_COMPARISON},
- [TOKEN_GREATER_EQUAL] = {NULL, binary, PREC_COMPARISON},
- [TOKEN_LESS] = {NULL, binary, PREC_COMPARISON},
- [TOKEN_LESS_EQUAL] = {NULL, binary, PREC_COMPARISON},
- [TOKEN_IDENTIFIER] = {variable, NULL, PREC_NONE},
- [TOKEN_STRING] = {string, NULL, PREC_NONE},
- [TOKEN_NUMBER] = {number, NULL, PREC_NONE},
- [TOKEN_AND] = {NULL, and_, PREC_AND},
- [TOKEN_CLASS] = {NULL, NULL, PREC_NONE},
- [TOKEN_ELSE] = {NULL, NULL, PREC_NONE},
- [TOKEN_FALSE] = {literal, NULL, PREC_NONE},
- [TOKEN_FOR] = {NULL, NULL, PREC_NONE},
- [TOKEN_FUN] = {NULL, NULL, PREC_NONE},
- [TOKEN_IF] = {NULL, NULL, PREC_NONE},
- [TOKEN_NIL] = {literal, NULL, PREC_NONE},
- [TOKEN_OR] = {NULL, or_, PREC_OR},
- [TOKEN_PRINT] = {NULL, NULL, PREC_NONE},
- [TOKEN_RETURN] = {NULL, NULL, PREC_NONE},
- [TOKEN_SUPER] = {super_, NULL, PREC_NONE},
- [TOKEN_THIS] = {this_, NULL, PREC_NONE},
- [TOKEN_TRUE] = {literal, NULL, PREC_NONE},
- [TOKEN_VAR] = {NULL, NULL, PREC_NONE},
- [TOKEN_WHILE] = {NULL, NULL, PREC_NONE},
- [TOKEN_ERROR] = {NULL, NULL, PREC_NONE},
- [TOKEN_EOF] = {NULL, NULL, PREC_NONE},
- };
- /// \brief 优先级处理
- /// \param precedence
- static void parsePrecedence(Precedence precedence) {
- advance();
- ParseFn prefixRule = getRule(parser.previous.type)->prefix;
- if (prefixRule == NULL) {
- error("Expect expression.");
- return;
- }
- bool canAssign = precedence <= PREC_ASSIGNMENT;
- prefixRule(canAssign);///! 执行具体函数
- while (precedence <= getRule(parser.current.type)->precedence) {
- advance();
- ParseFn infixRule = getRule(parser.previous.type)->infix;
- infixRule(canAssign);///! 执行具体函数
- }
- if (canAssign && match(TOKEN_EQUAL)) {
- error("Invalid assignment target.");
- }
- }
- static uint8_t identifierConstant(Token *name) {
- return makeConstant(OBJ_VAL(copyString(name->start, name->length)));
- }
- static bool identifiersEqual(Token *a, Token *b) {
- if (a->length != b->length) return false;
- return memcmp(a->start, b->start, a->length) == 0;
- }
- static void addLocal(Token name) {
- if (current->localCount == UINT8_COUNT) {
- error("Too many local variables in function.");
- return;
- }
- Local *local = ¤t->locals[current->localCount++];
- local->name = name;
- local->depth = -1;// 未初始化
- local->isCaptured = false;
- }
- static void declareVariable() {
- if (current->scopeDepth == 0) return;
- Token *name = &parser.previous;
- // we detect the error like:
- // {
- // var a = "first";
- // var a = "second";
- // }
- for (int i = current->localCount - 1; i >= 0; i--) {
- Local *local = ¤t->locals[i];
- if (local->depth != -1 && local->depth < current->scopeDepth) {
- break;
- }
- if (identifiersEqual(name, &local->name)) {
- error("Already a variable with the name in this scope.");
- }
- }
- addLocal(*name);
- }
- static uint8_t parseVariable(const char *errorMessage) {
- consume(TOKEN_IDENTIFIER, errorMessage);
- declareVariable();// 处理本地变量
- if (current->scopeDepth > 0) return 0;
- return identifierConstant(&parser.previous);
- }
- static void markInitialized() {
- if (current->scopeDepth == 0) return;
- current->locals[current->localCount - 1].depth = current->scopeDepth;
- }
- static void defineVariable(uint8_t global) {
- if (current->scopeDepth > 0) {
- // markInitialized 未初始化时值 为 -1
- markInitialized();
- // 本地变量,直接退出
- return;
- }
- emitBytes(OP_DEFINE_GLOBAL, global);
- }
- static ParseRule *getRule(TokenType type) {
- return &rules[type];
- }
- /**
- ******************************************************************************
- * statement → exprStmt
- | forStmt
- | ifStmt
- | printStmt
- | returnStmt
- | whileStmt
- | block ;
- block → "{" declaration* "}" ;
- declaration → classDecl
- | funDecl
- | varDecl
- | statement ;
- ******************************************************************************
- */
- ObjFunction *compile(const char *source) {
- initScanner(source);
- Compiler compiler;
- initCompiler(&compiler, TYPE_SCRIPT);
- parser.hadError = false;
- parser.panicMode = false;
- advance();
- while (!match(TOKEN_EOF)) {
- declaration();
- }
- ObjFunction *function = endCompiler();
- return parser.hadError ? NULL : function;
- }
- void markCompilerRoots() {
- Compiler *compiler = current;
- while (compiler != NULL) {
- markObject((Obj *) compiler->function);
- compiler = compiler->enclosing;
- }
- }
|