Chapter 24.4
This commit is contained in:
parent
ce478b0b80
commit
44e47b89de
1 changed files with 48 additions and 6 deletions
|
@ -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 = ¤t->locals[current->localCount++];
|
Local *local = ¤t->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();
|
||||||
|
|
Loading…
Reference in a new issue