blob: 07928d2cc5256975bb78c62437e724a67ac4bb46 [file] [log] [blame]
swissChilica107a02021-04-14 12:07:30 -07001#pragma once
2
3#include "lisp.h"
swissChilif3e7f182021-04-20 13:57:22 -07004#include <dasm_proto.h>
swissChilica107a02021-04-14 12:07:30 -07005#include <stdbool.h>
swissChilib3ca4fb2021-04-20 10:33:00 -07006#include <stdint.h>
swissChilica107a02021-04-14 12:07:30 -07007
swissChili2999dd12021-07-02 14:19:53 -07008enum namespace
9{
swissChiliddc97542021-07-04 11:47:42 -070010 /// A function
swissChili2999dd12021-07-02 14:19:53 -070011 NS_FUNCTION,
swissChiliddc97542021-07-04 11:47:42 -070012 /// A macro
swissChili2999dd12021-07-02 14:19:53 -070013 NS_MACRO,
swissChiliddc97542021-07-04 11:47:42 -070014 /// An anonymous function (a lambda/closure)
15 NS_ANONYMOUS,
swissChili2999dd12021-07-02 14:19:53 -070016};
17
swissChilica107a02021-04-14 12:07:30 -070018struct function
19{
20 char *name;
21 int nargs; // number of arguments
swissChili2999dd12021-07-02 14:19:53 -070022 enum namespace namespace;
swissChilica107a02021-04-14 12:07:30 -070023
swissChili2999dd12021-07-02 14:19:53 -070024 union
25 {
swissChili53472e82021-05-08 16:06:32 -070026 value_t (*def0)();
27 value_t (*def1)(value_t);
28 value_t (*def2)(value_t, value_t);
29 value_t (*def3)(value_t, value_t, value_t);
swissChilica107a02021-04-14 12:07:30 -070030 void *code_ptr;
swissChilif3e7f182021-04-20 13:57:22 -070031 uintptr_t code_addr;
swissChilica107a02021-04-14 12:07:30 -070032 };
33
34 struct function *prev;
35};
36
37struct environment
38{
39 struct function *first;
40};
41
swissChili923b5362021-05-09 20:31:43 -070042enum var_type
43{
44 V_BOUND, // Bound local variable
45 V_ARGUMENT, // Bound function argument
46 V_GLOBAL, // Global variable
47 V_FREE // Free (lexical) variable
48};
49
swissChilica107a02021-04-14 12:07:30 -070050struct variable
51{
52 char *name;
swissChili923b5362021-05-09 20:31:43 -070053 uintptr_t number;
54 enum var_type type;
swissChilica107a02021-04-14 12:07:30 -070055 struct variable *prev;
56};
57
swissChilif1ba8c12021-07-02 18:45:38 -070058/// Local environment
swissChilica107a02021-04-14 12:07:30 -070059struct local
60{
swissChilif1ba8c12021-07-02 18:45:38 -070061 /// Parent environment, NULL if none (root).
62 struct local *parent;
63
swissChilica107a02021-04-14 12:07:30 -070064 int num_vars;
swissChilif1ba8c12021-07-02 18:45:38 -070065 /// Most recently defined variable
swissChilica107a02021-04-14 12:07:30 -070066 struct variable *first;
swissChili53472e82021-05-08 16:06:32 -070067 int npc;
68 int nextpc;
swissChili67bdf282021-06-06 18:46:08 -070069 bool *stack_slots;
swissChiliddc97542021-07-04 11:47:42 -070070 /// Number of slots allocated in `stack_slots`
71 int num_stack_slots;
72 /// Number of entries used in `stack_slots`
73 int num_stack_entries;
74 /// Number of closure slots total (allocated as V_FREE variables)
75 int num_closure_slots;
swissChilica107a02021-04-14 12:07:30 -070076};
77
swissChili53472e82021-05-08 16:06:32 -070078void compile_expression(struct environment *env, struct local *local,
79 value_t val, dasm_State **Dst);
swissChili6b47b6d2021-06-30 22:08:55 -070080
81/**
swissChiliddc97542021-07-04 11:47:42 -070082 * Compile a function
83 * @param args The function args and body, e.g. `((b c) d)`
84 * @param namespace The function namespace.
85 * @param env The environment.
86 * @param local_out The local environment generated for this function will be
87 * returned here. NULL if you do not care about it being returned (you probably
88 * should since you need to free the stack slot allocation map).
89 * @param local_parent Parent local environment, only needed for closures. NULL
90 * if no parent.
91 * @param nargs The number of arguments for this function will be returned here.
92 * NULL if you don't care about it.
93 * @returns The compiled function state. You should probably give this to
94 * `add_function` or something similar.
95 */
96struct dasm_State *compile_function(value_t args, enum namespace namespace,
97 struct environment *env, struct local *local_out,
98 struct local *local_parent, int *nargs);
99
100void compile_variable(struct variable *v, dasm_State *Dst);
101
102/**
swissChili6b47b6d2021-06-30 22:08:55 -0700103 * Compile a backquoted expression
104 */
105void compile_backquote(struct environment *env, struct local *local,
106 value_t val, dasm_State **Dst);
107
swissChili53472e82021-05-08 16:06:32 -0700108void compile_expr_to_func(struct environment *env, char *name, value_t val,
109 dasm_State **Dst);
swissChili6b47b6d2021-06-30 22:08:55 -0700110
swissChili53472e82021-05-08 16:06:32 -0700111int nextpc(struct local *local, dasm_State **Dst);
swissChili67bdf282021-06-06 18:46:08 -0700112
113// Local utilities
114unsigned int local_alloc(struct local *local);
115void local_free(struct local *local, unsigned int slot);
116
swissChilif1ba8c12021-07-02 18:45:38 -0700117/**
118 * Walk `body` and reserve space in `local` for any variable declarations.
119 */
swissChili67bdf282021-06-06 18:46:08 -0700120void walk_and_alloc(struct local *local, value_t body);
swissChili8fc5e2f2021-04-22 13:45:10 -0700121// Compile top-level declaration
swissChili53472e82021-05-08 16:06:32 -0700122void compile_tl(value_t val, struct environment *env);
123struct environment compile_all(struct istream *is);
124struct function *find_function(struct environment *env, char *name);
swissChili923b5362021-05-09 20:31:43 -0700125struct variable *add_variable(struct local *local, enum var_type type,
126 char *name, int number);
swissChiliddc97542021-07-04 11:47:42 -0700127
128/**
129 * Find a variable in `local` with name `name`.
130 * @returns The variable, NULL if not found.
131 */
swissChili923b5362021-05-09 20:31:43 -0700132struct variable *find_variable(struct local *local, char *name);
swissChiliddc97542021-07-04 11:47:42 -0700133
swissChili923b5362021-05-09 20:31:43 -0700134void destroy_local(struct local *local);
swissChili2999dd12021-07-02 14:19:53 -0700135
136/**
137 * Like `apply` in lisp, calls func with list args and returns the result.
138 */
139value_t call_list(struct function *func, value_t list);
swissChiliddc97542021-07-04 11:47:42 -0700140value_t call_list_closure(struct closure *c, value_t list);