aboutsummaryrefslogtreecommitdiff
path: root/include/posthaste/lower.h
blob: f7699ecb26566be59be595bbe399b269e57bf03a (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
#ifndef POSTHASTE_LOWER_H
#define POSTHASTE_LOWER_H

/* stuff related to lowering AST to bytecode */

#include <posthaste/ast.h>
#include <posthaste/vec.h>
#include <ejit/ejit.h>

enum insn_kind {
	LABEL, /* no-op during interpretation,
	          used by JIT engine to keep track of jump branch destinations.
	          Each branch/jump must have a corresponding label!*/
	CALL,
	MOVE,
	ADD,
	SUB,
	MUL,
	DIV,
	ARG, /* push location to arg stack */
	RETVAL, /* move return value to location */
	PRINT_DATE,
	PRINT_STRING,
	PRINT_INT,
	PRINT_BOOL,
	PRINT_NEWLINE,
	PRINT_SPACE,
	DATE_ADD,
	DATE_SUB,
	DATE_DIFF,
	STORE_DAY, /* x.day etc */
	STORE_MONTH,
	STORE_YEAR,
	LOAD_DAY, /* x'day etc */
	LOAD_MONTH,
	LOAD_YEAR,
	LOAD_WEEKDAY,
	LOAD_WEEKNUM,
	TODAY, /* the builtin Today() is lowered to a single instruction */
	RET, /* return with value */
	STOP, /* return without value */
	CONST, /* push a constant value to loc */
	EQ,
	LT,
	NEG, /* negation, -x */
	B, /* branch if non-zero */
	BZ, /* branch if zero */
	J, /* jump */
};

struct insn {
	enum insn_kind k;
	/* output location */
	struct loc o;

	/* input locations */
	struct loc i0;
	struct loc i1;

	/* potential constant value */
	union {
		int64_t v;
		char *s;
	};
};

/* after lowering, there's no real difference between posthaste 'functions' and
 * 'procedures', so I just use fn to refer to either or */
struct fn {
	char *name;

	size_t idx;

	/* virtual stack pointer used during lowering to choose where to place
	 * values */
	size_t sp;

	/* maximum stack pointer value to know how much stack space to allocate */
	size_t max_sp;

	/* used by jit */
	/* how many formal parameters */
	size_t params;

	struct ejit_func *f;
};

int lower_ast(struct ast *tree);

struct fn *find_fn(size_t idx);
size_t num_globals();

void destroy_lowering();

static inline bool is_null_loc(struct loc l)
{
	return l.g == 1 && l.s == 0;
}

#endif /* POSTHASTE_LOWER_H */