aboutsummaryrefslogtreecommitdiff
path: root/paradox.false
blob: 7d10f93803952f664b2b09cd64651b3a2dc7670c (plain)
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
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
{
	variables:

	c: current_char
	q: state: 0=CONTINUE, 1=DONE, 2=ERROR

	f: fn_counter
	s: str_counter

	i: current_int

	l: line_number
	p: line_position

	x: compile_fn
	r: read_char
	e: error
}

0  f: { fn_counter <- 0 }
0  s: { str_counter <- 0 }
1_ i: { current_int <- -1 }

1  l: { line_number <- 1 }
0  p: { line_position <- 0 }

{ read_char() }
[
	^ { input <- getchar() }
	{ if input = newline }
	$10=$[
		l; 1+ l: { increment line_number }
		0 p:     { reset line_position }
	]?
	{ else }
	~[
		p; 1+ p: { increment line_position }
	]?
]r:

{ error(condition, message) }
[
	{ if condition}
	\ [
		10,"%fatal FALSE syntax error at " { first part of error message }
		l;.":"p;.": "                      { print line_number and line_position }
		$! 10,                             { call message }
		2q:                                { state <- ERROR }
	]?
	% { pop message }
]e:

{ compile_fn() }
[
	f;      { push fn_counter }
	$ 1+ f: { increment fn_counter }

	"fun_" $. ":" 10, { emit label }

	{
		string stack layout, from top to bottom:

		repeat:
			id (if -1, we've reached the end)
			length
			last .. first char
	}
	1_ { string stack end }

	0  q: { state <- CONTINUE }
	1_ c: { current_char <- EOF }

	{ while state == CONTINUE }
	[q;0=][
		{ if current_char = EOF }
		c;1_=[
			r;! c: { current_char <- read_char() }
		]?

		{ if '0'-1 < c < '9'+1 }
		c;$ '0 1- > \ '9 1+ \ > & $[
			i;1_=[0 i:]?       { if current_int = -1: current_int <- 0 }
			i; 10* c; '0- + i: { current_int = current_int * 10 + current_char - '0'
			1_ c:              { consume current_char }
		]?

		{ elseif current_int != -1 }
		i;1_=~ $[%~1_\]?[
			{ emit push int }
			"sub r12, 8" 10,
			"mov qword[r12], " i;. 10,

			1_ i: { clear current_int }
		]?

		{ elseif a-1 < c < z+1 }
		c;$ 'a 1- > \ 'z 1+ \ > & $[%~1_\]?[
			{ emit push var ref }
			"sub r12, 8" 10,
			"mov qword[r12], var_" c;, 10,
		]?

		{ elseif c = ' }
		c;''= $[%~1_\]?[
			r;! { read character literal }
			$1_=["unterminated char literal"]e;! { check for EOF }
			{ if state != ERROR }
			q;2=~ [
				{ emit push char }
				"sub r12, 8" 10,
				"mov qword[r12], " . 10,
			]?
		]?

		{ elseif c = " }
		c;'"= $[%~1_\]?[
			% { drop true to manipulate stack below }
			0 { length <- 0 }

			{ while read_char() != " and state != ERROR }
			[
				r;!           { push read_char() }
				$1_=["unterminated string literal"]e;! { check for EOF }
				$'"=~ q;2=~ & { condition }
			][
				\  { swap length to top }
				1+ { increment length }
			]#
			% { drop " or EOF }

			{ if state != ERROR }
			q;2=~ [
				s;      { id <- str_counter }
				$ 1+ s: { increment str_counter }

				{ emit print string }
				"mov rax, 1" 10,
				"mov rdi, 1" 10,
				"mov rsi, str_" 0 ø . 10,
				"mov rdx, "     1 ø . 10,
				"syscall" 10,

				1_ c: { consume current_char }
			]?

			1_ { push true }
		]?

		{ elseif c = [ }
		c;'[= $[%~1_\]?[
			f;                 { backup fn_id }
			"jmp end_" f;. 10, { skip generated code }
			x;!                { call compile_fn }

			{ if state = ERROR }
			q;2=[
				{ stack is corrupted now }
				1_ { push true to skip remaining elseif branches }
			]?

			q;2=~ c;']=~ & ["unterminated lambda"]e;! { ensure current_char was ] }

			{ if state != ERROR }
			q;2=~ [
				{ emit push fn ref }
				{ fn_id is top }
				"sub r12, 8" 10,
				"mov qword[r12], fun_" . 10,

				0  q: { state <- CONTINUE }
				1_ c: { clear current_char }
			]?
		]?

		{ elseif c is whitespace }
		c;9= c;10= | c;32= | $[%~1_\]?[
			1_ c: { consume current_char }
		]?

		{ elseif c = EOF or c = ] }
		c;1_= c;']= | $[%~1_\]?[
			1 q: { state <- DONE }
		]?

		{ elseif c is UTF-8 }
		c;195= $[%~1_\]?[
			r;! c: { c <- read_char() }

			c;184=         $[ 'O c:	]? { if c = ø then c <- O }
			c;159= $[%~1_\]?[ 'B c:	]? { if c = ß then c <- B }
			~["unknown UTF-8 character"]e;! { else error }
		]?

		{ elseif c = ø then c <- O }
		c;248= $[%~1_\]?[ 'O c: ]?

		{ elseif c = ß then c <- B }
		c;223= $[%~1_\]?[ 'B c: ]?

		{ elseif c = { }
		c;'{= $[%~1_\]?[
			[r;!'}=~][]# { while read_char() != (closing bracket) }
			1_ c:        { clear current_char }
		]?

		{ else error }
		~["unknown character: "c;,]e;!
	]#

	{ if state != ERROR }
	q;2=~[
		"ret" 10, { emit return to caller }

		{ string stack is top }
		{ while top != -1 }
		[$1_=~][
			{ id is top }
			"str_" . ": db " { emit label }

			{ length is top }
			$ { copy length }

			{ print string }
			{ while length > 0}
			[$ 0 >][
				$ 1+ ø .     { print nth item }
				1-           { decrement length }
				$ 0 > [","]? { if length > 0 emit , }
			]#
			% { drop 0 }

			{ remove string }
			{ while length > 0 }
			[$ 0 >][
				\  { swap last char with length }
				%  { drop last char }
				1- { decrement length }
			]#
			% { drop 0 }

			10, { newline }
		]#
		% { drop string stack end }

		{ function counter is top now }
		"end_" . ":" 10, { end label }
	]?
] x:

"section .text" 10,

x;! { call compile_fn }

{ if state != ERROR }
q;2=~[

{ emit setup and stack }

1000000
"global _start
_start:
lea r12, [stack+8*"$."]
call fun_0
mov rax, 60
mov rdi, 0
syscall
section .bss
stack: resq "."
"

{ emit variables }

"section .data" 10,

'a { iter <- a}
{ while iter != z+1}
[$ 'z1+ =~][
	"var_" $, ": dq 0" 10, { emit allocation }
	1+                     { increment iter }
]#
% { drop iter }

]?