Chapter 24.4

This commit is contained in:
Tom Willemse 2022-03-13 19:41:34 -07:00
parent ce478b0b80
commit 44e47b89de

View file

@ -46,7 +46,8 @@ typedef struct {
typedef enum { TYPE_FUNCTION, TYPE_SCRIPT } FunctionType; typedef enum { TYPE_FUNCTION, TYPE_SCRIPT } FunctionType;
typedef struct { typedef struct Compiler {
struct Compiler *enclosing;
ObjFunction *function; ObjFunction *function;
FunctionType type; FunctionType type;
@ -171,12 +172,17 @@ static void patchJump(int offset) {
} }
static void initCompiler(Compiler *compiler, FunctionType type) { static void initCompiler(Compiler *compiler, FunctionType type) {
compiler->enclosing = current;
compiler->function = NULL; compiler->function = NULL;
compiler->type = type; compiler->type = type;
compiler->localCount = 0; compiler->localCount = 0;
compiler->scopeDepth = 0; compiler->scopeDepth = 0;
compiler->function = newFunction(); compiler->function = newFunction();
current = compiler; current = compiler;
if (type != TYPE_SCRIPT) {
current->function->name =
copyString(parser.previous.start, parser.previous.length);
}
Local *local = &current->locals[current->localCount++]; Local *local = &current->locals[current->localCount++];
local->depth = 0; local->depth = 0;
@ -196,6 +202,7 @@ static ObjFunction *endCompiler() {
} }
#endif #endif
current = current->enclosing;
return function; return function;
} }
@ -288,6 +295,43 @@ static void block() {
consume(TOKEN_RIGHT_BRACE, "Expect '}' after block."); consume(TOKEN_RIGHT_BRACE, "Expect '}' after block.");
} }
static void function(FunctionType type) {
Compiler compiler;
initCompiler(&compiler, type);
beginScope();
consume(TOKEN_LEFT_PAREN, "Expect '(' after function name.");
if (!check(TOKEN_RIGHT_PAREN)) {
do {
current->function->arity++;
if (current->function->arity > 255) {
errorAtCurrent("Can't have more than 250 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.");
block();
ObjFunction *function = endCompiler();
emitBytes(OP_CONSTANT, makeConstant(OBJ_VAL(function)));
}
static void markInitialized() {
if (current->scopeDepth == 0)
return;
current->locals[current->localCount - 1].depth = current->scopeDepth;
}
static void funDeclaration() {
uint8_t global = parseVariable("Expect function name.");
markInitialized();
function(TYPE_FUNCTION);
defineVariable(global);
}
static void varDeclaration() { static void varDeclaration() {
uint8_t global = parseVariable("Expect variable name."); uint8_t global = parseVariable("Expect variable name.");
@ -417,7 +461,9 @@ static void synchronize() {
} }
static void declaration() { static void declaration() {
if (match(TOKEN_VAR)) { if (match(TOKEN_FUN)) {
funDeclaration();
} else if (match(TOKEN_VAR)) {
varDeclaration(); varDeclaration();
} else { } else {
statement(); statement();
@ -653,10 +699,6 @@ static uint8_t parseVariable(const char *errorMessage) {
return identifierConstant(&parser.previous); return identifierConstant(&parser.previous);
} }
static void markInitialized() {
current->locals[current->localCount - 1].depth = current->scopeDepth;
}
static void defineVariable(uint8_t global) { static void defineVariable(uint8_t global) {
if (current->scopeDepth > 0) { if (current->scopeDepth > 0) {
markInitialized(); markInitialized();