Skip to content

Commit d1a2192

Browse files
committed
feat: add function declarations
1 parent 8208490 commit d1a2192

1 file changed

Lines changed: 60 additions & 4 deletions

File tree

src/compiler.c

Lines changed: 60 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414
#include "debug.h"
1515
#endif
1616

17+
#define PARAMETERS_MAX 255
18+
1719
typedef struct
1820
{
1921
Token previous;
@@ -59,10 +61,11 @@ typedef enum
5961
TYPE_SCRIPT,
6062
} FunctionType;
6163

62-
typedef struct
64+
typedef struct Compiler
6365
{
64-
ObjFunction* function;
65-
FunctionType type;
66+
struct Compiler* enclosing;
67+
ObjFunction* function;
68+
FunctionType type;
6669

6770
Local locals[UINT8_COUNT];
6871
int local_count;
@@ -212,12 +215,19 @@ static void patch_jump(int offset)
212215
}
213216
static void init_compiler(Compiler* compiler, FunctionType type)
214217
{
218+
compiler->enclosing = current;
215219
compiler->function = NULL;
216220
compiler->type = type;
217221
compiler->local_count = 0;
218222
compiler->scope_depth = 0;
219223
current = compiler;
220224

225+
if (type != TYPE_SCRIPT)
226+
{
227+
current->function->name =
228+
copy_string(parser.previous.start, parser.previous.length);
229+
}
230+
221231
Local* local = &current->locals[current->local_count++];
222232
local->depth = 0;
223233
local->name.start = "";
@@ -236,6 +246,7 @@ static ObjFunction* end_compiler()
236246
: "<script>");
237247
#endif
238248

249+
current = current->enclosing;
239250
return function;
240251
}
241252

@@ -337,6 +348,8 @@ static u8 parse_variable(bool is_immutable, char* error_message)
337348

338349
static void mark_initialized()
339350
{
351+
if (current->scope_depth == 0)
352+
return;
340353
current->locals[current->local_count - 1].depth = current->scope_depth;
341354
}
342355

@@ -611,6 +624,45 @@ static void block()
611624
consume(TOKEN_RIGHT_BRACE, "Expect '}' after block");
612625
}
613626

627+
static void function(FunctionType type)
628+
{
629+
Compiler compiler;
630+
init_compiler(&compiler, type);
631+
begin_scope();
632+
633+
consume(TOKEN_LEFT_PAREN, "Expect '(' after function name");
634+
635+
if (!check(TOKEN_RIGHT_PAREN))
636+
{
637+
do
638+
{
639+
if (++current->function->arity > PARAMETERS_MAX)
640+
{
641+
error_at_current("Can't have more than 255 parameters");
642+
}
643+
644+
u8 param_const = parse_variable(false, "Expect parameter name");
645+
define_variable(param_const, false);
646+
647+
} while (match(TOKEN_COMMA));
648+
}
649+
consume(TOKEN_RIGHT_PAREN, "Expect ')' after function parameters");
650+
651+
consume(TOKEN_LEFT_BRACE, "Expect '{' before function body");
652+
block();
653+
654+
ObjFunction* function = end_compiler();
655+
emit_bytes(OP_CONSTANT, make_constant(OBJ_VAL(function)));
656+
}
657+
658+
static void fun_declaration()
659+
{
660+
u8 global = parse_variable(false, "Expect function name");
661+
mark_initialized();
662+
function(TYPE_FUNCTION);
663+
define_variable(global, false);
664+
}
665+
614666
static void var_declaration()
615667
{
616668
bool is_immutable = parser.previous.type == TOKEN_VAL;
@@ -766,7 +818,11 @@ static void synchronize()
766818

767819
static void declaration()
768820
{
769-
if (match(TOKEN_VAR) || match(TOKEN_VAL))
821+
if (match(TOKEN_FUN))
822+
{
823+
fun_declaration();
824+
}
825+
else if (match(TOKEN_VAR) || match(TOKEN_VAL))
770826
var_declaration();
771827
else
772828
statement();

0 commit comments

Comments
 (0)