aboutsummaryrefslogtreecommitdiffstats
path: root/clox/src/compiler.c
diff options
context:
space:
mode:
authorGravatar Tom Willemse2022-03-13 19:41:34 -0700
committerGravatar Tom Willemse2022-03-13 19:41:34 -0700
commit44e47b89de9e7d9f7d86e1f7d532b70c952a8ab3 (patch)
tree95bbd40da2dbb1108b05a3b6f8d48f38827fb845 /clox/src/compiler.c
parentce478b0b80af331b89813148df7b04d46968e328 (diff)
downloadcrafting-interpreters-44e47b89de9e7d9f7d86e1f7d532b70c952a8ab3.tar.gz
crafting-interpreters-44e47b89de9e7d9f7d86e1f7d532b70c952a8ab3.zip
Chapter 24.4
Diffstat (limited to 'clox/src/compiler.c')
-rw-r--r--clox/src/compiler.c54
1 files changed, 48 insertions, 6 deletions
diff --git a/clox/src/compiler.c b/clox/src/compiler.c
index 44eede8..bd835f2 100644
--- a/clox/src/compiler.c
+++ b/clox/src/compiler.c
@@ -46,7 +46,8 @@ typedef struct {
typedef enum { TYPE_FUNCTION, TYPE_SCRIPT } FunctionType;
-typedef struct {
+typedef struct Compiler {
+ struct Compiler *enclosing;
ObjFunction *function;
FunctionType type;
@@ -171,12 +172,17 @@ static void patchJump(int offset) {
}
static void initCompiler(Compiler *compiler, FunctionType type) {
+ compiler->enclosing = current;
compiler->function = NULL;
compiler->type = type;
compiler->localCount = 0;
compiler->scopeDepth = 0;
compiler->function = newFunction();
current = compiler;
+ if (type != TYPE_SCRIPT) {
+ current->function->name =
+ copyString(parser.previous.start, parser.previous.length);
+ }
Local *local = &current->locals[current->localCount++];
local->depth = 0;
@@ -196,6 +202,7 @@ static ObjFunction *endCompiler() {
}
#endif
+ current = current->enclosing;
return function;
}
@@ -288,6 +295,43 @@ static void 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() {
uint8_t global = parseVariable("Expect variable name.");
@@ -417,7 +461,9 @@ static void synchronize() {
}
static void declaration() {
- if (match(TOKEN_VAR)) {
+ if (match(TOKEN_FUN)) {
+ funDeclaration();
+ } else if (match(TOKEN_VAR)) {
varDeclaration();
} else {
statement();
@@ -653,10 +699,6 @@ static uint8_t parseVariable(const char *errorMessage) {
return identifierConstant(&parser.previous);
}
-static void markInitialized() {
- current->locals[current->localCount - 1].depth = current->scopeDepth;
-}
-
static void defineVariable(uint8_t global) {
if (current->scopeDepth > 0) {
markInitialized();