1#ifndef wren_compiler_h
2#define wren_compiler_h
3
4#include "wren.h"
5#include "wren_value.h"
6
7typedef struct sCompiler Compiler;
8
9// This module defines the compiler for Wren. It takes a string of source code
10// and lexes, parses, and compiles it. Wren uses a single-pass compiler. It
11// does not build an actual AST during parsing and then consume that to
12// generate code. Instead, the parser directly emits bytecode.
13//
14// This forces a few restrictions on the grammar and semantics of the language.
15// Things like forward references and arbitrary lookahead are much harder. We
16// get a lot in return for that, though.
17//
18// The implementation is much simpler since we don't need to define a bunch of
19// AST data structures. More so, we don't have to deal with managing memory for
20// AST objects. The compiler does almost no dynamic allocation while running.
21//
22// Compilation is also faster since we don't create a bunch of temporary data
23// structures and destroy them after generating code.
24
25// Compiles [source], a string of Wren source code located in [module], to an
26// [ObjFn] that will execute that code when invoked. Returns `NULL` if the
27// source contains any syntax errors.
28//
29// If [isExpression] is `true`, [source] should be a single expression, and
30// this compiles it to a function that evaluates and returns that expression.
31// Otherwise, [source] should be a series of top level statements.
32//
33// If [printErrors] is `true`, any compile errors are output to stderr.
34// Otherwise, they are silently discarded.
35ObjFn* wrenCompile(WrenVM* vm, ObjModule* module, const char* source,
36 bool isExpression, bool printErrors);
37
38// When a class is defined, its superclass is not known until runtime since
39// class definitions are just imperative statements. Most of the bytecode for a
40// a method doesn't care, but there are two places where it matters:
41//
42// - To load or store a field, we need to know the index of the field in the
43// instance's field array. We need to adjust this so that subclass fields
44// are positioned after superclass fields, and we don't know this until the
45// superclass is known.
46//
47// - Superclass calls need to know which superclass to dispatch to.
48//
49// We could handle this dynamically, but that adds overhead. Instead, when a
50// method is bound, we walk the bytecode for the function and patch it up.
51void wrenBindMethodCode(ObjClass* classObj, ObjFn* fn);
52
53// Reaches all of the heap-allocated objects in use by [compiler] (and all of
54// its parents) so that they are not collected by the GC.
55void wrenMarkCompiler(WrenVM* vm, Compiler* compiler);
56
57#endif
58