blob: 16cc35ed1df9b3f6d83c791390c1f4edb0c1b3d9 [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
swissChili74348422021-07-04 13:23:24 -070064 /// Name that the current function should be referred to by, e.g. `recurse`
65 /// for a lambda.
66 char *current_function_name;
67
68 int num_vars, num_args;
swissChilif1ba8c12021-07-02 18:45:38 -070069 /// Most recently defined variable
swissChilica107a02021-04-14 12:07:30 -070070 struct variable *first;
swissChili53472e82021-05-08 16:06:32 -070071 int npc;
72 int nextpc;
swissChili67bdf282021-06-06 18:46:08 -070073 bool *stack_slots;
swissChiliddc97542021-07-04 11:47:42 -070074 /// Number of slots allocated in `stack_slots`
75 int num_stack_slots;
76 /// Number of entries used in `stack_slots`
77 int num_stack_entries;
78 /// Number of closure slots total (allocated as V_FREE variables)
79 int num_closure_slots;
swissChilica107a02021-04-14 12:07:30 -070080};
81
swissChili53472e82021-05-08 16:06:32 -070082void compile_expression(struct environment *env, struct local *local,
83 value_t val, dasm_State **Dst);
swissChili6b47b6d2021-06-30 22:08:55 -070084
85/**
swissChiliddc97542021-07-04 11:47:42 -070086 * Compile a function
87 * @param args The function args and body, e.g. `((b c) d)`
88 * @param namespace The function namespace.
89 * @param env The environment.
90 * @param local_out The local environment generated for this function will be
91 * returned here. NULL if you do not care about it being returned (you probably
92 * should since you need to free the stack slot allocation map).
93 * @param local_parent Parent local environment, only needed for closures. NULL
94 * if no parent.
95 * @param nargs The number of arguments for this function will be returned here.
96 * NULL if you don't care about it.
97 * @returns The compiled function state. You should probably give this to
98 * `add_function` or something similar.
99 */
100struct dasm_State *compile_function(value_t args, enum namespace namespace,
101 struct environment *env, struct local *local_out,
swissChili74348422021-07-04 13:23:24 -0700102 struct local *local_parent, int *nargs, char *name);
swissChiliddc97542021-07-04 11:47:42 -0700103
104void compile_variable(struct variable *v, dasm_State *Dst);
105
106/**
swissChili6b47b6d2021-06-30 22:08:55 -0700107 * Compile a backquoted expression
108 */
109void compile_backquote(struct environment *env, struct local *local,
110 value_t val, dasm_State **Dst);
111
swissChili53472e82021-05-08 16:06:32 -0700112void compile_expr_to_func(struct environment *env, char *name, value_t val,
113 dasm_State **Dst);
swissChili6b47b6d2021-06-30 22:08:55 -0700114
swissChili53472e82021-05-08 16:06:32 -0700115int nextpc(struct local *local, dasm_State **Dst);
swissChili67bdf282021-06-06 18:46:08 -0700116
117// Local utilities
118unsigned int local_alloc(struct local *local);
119void local_free(struct local *local, unsigned int slot);
120
swissChilif1ba8c12021-07-02 18:45:38 -0700121/**
122 * Walk `body` and reserve space in `local` for any variable declarations.
123 */
swissChili67bdf282021-06-06 18:46:08 -0700124void walk_and_alloc(struct local *local, value_t body);
swissChili8fc5e2f2021-04-22 13:45:10 -0700125// Compile top-level declaration
swissChili53472e82021-05-08 16:06:32 -0700126void compile_tl(value_t val, struct environment *env);
127struct environment compile_all(struct istream *is);
128struct function *find_function(struct environment *env, char *name);
swissChili923b5362021-05-09 20:31:43 -0700129struct variable *add_variable(struct local *local, enum var_type type,
130 char *name, int number);
swissChiliddc97542021-07-04 11:47:42 -0700131
132/**
133 * Find a variable in `local` with name `name`.
134 * @returns The variable, NULL if not found.
135 */
swissChili923b5362021-05-09 20:31:43 -0700136struct variable *find_variable(struct local *local, char *name);
swissChiliddc97542021-07-04 11:47:42 -0700137
swissChili923b5362021-05-09 20:31:43 -0700138void destroy_local(struct local *local);
swissChili2999dd12021-07-02 14:19:53 -0700139
140/**
141 * Like `apply` in lisp, calls func with list args and returns the result.
142 */
143value_t call_list(struct function *func, value_t list);
swissChiliddc97542021-07-04 11:47:42 -0700144value_t call_list_closure(struct closure *c, value_t list);