String.trim
This commit is contained in:
@@ -4,11 +4,11 @@ A very cool language
|
|||||||
|
|
||||||
## Huh?
|
## Huh?
|
||||||
* Indentation-based syntax
|
* Indentation-based syntax
|
||||||
* Compiled to x86_64 Assembly
|
* Compiles to x86_64 Assembly
|
||||||
* Sometimes works
|
* Sometimes works
|
||||||
|
|
||||||
## Syntax
|
## Syntax
|
||||||
```swift
|
```rust
|
||||||
func fib[n: I64] : I64
|
func fib[n: I64] : I64
|
||||||
if n <= 1
|
if n <= 1
|
||||||
return n
|
return n
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ func main[] : I64
|
|||||||
let s: I64 = 1
|
let s: I64 = 1
|
||||||
let j: I64 = 0
|
let j: I64 = 0
|
||||||
while j < 13
|
while j < 13
|
||||||
s = s * Char.to_i64(String.nth(n, i + j))
|
s = s * Char.parse_i64(String.nth(n, i + j))
|
||||||
j = j + 1
|
j = j + 1
|
||||||
if s > out
|
if s > out
|
||||||
out = s
|
out = s
|
||||||
|
|||||||
@@ -1,11 +1,13 @@
|
|||||||
func quicksort[arr: Array] : I64
|
func quicksort[arr: Array] : I64
|
||||||
do_quicksort(arr, 0, Array.size(arr)-1)
|
do_quicksort(arr, 0, Array.size(arr)-1)
|
||||||
|
return 0
|
||||||
|
|
||||||
func do_quicksort[arr: Array, low: I64, high: I64] : I64
|
func do_quicksort[arr: Array, low: I64, high: I64] : I64
|
||||||
if low < high
|
if low < high
|
||||||
let i: I64 = partition(arr, low, high)
|
let i: I64 = partition(arr, low, high)
|
||||||
do_quicksort(arr, low, i - 1)
|
do_quicksort(arr, low, i - 1)
|
||||||
do_quicksort(arr, i + 1, high)
|
do_quicksort(arr, i + 1, high)
|
||||||
|
return 0
|
||||||
|
|
||||||
func partition[arr: Array, low: I64, high: I64] : I64
|
func partition[arr: Array, low: I64, high: I64] : I64
|
||||||
let pivot: I64 = Array.nth(arr, high)
|
let pivot: I64 = Array.nth(arr, high)
|
||||||
|
|||||||
@@ -15,14 +15,13 @@ func rule110_step[state: Array] : Array
|
|||||||
return new_state
|
return new_state
|
||||||
|
|
||||||
func to_str[state: Array]: String
|
func to_str[state: Array]: String
|
||||||
// TODO: very leaky
|
let out: String = malloc(Array.size(state))
|
||||||
let o: String = ""
|
|
||||||
for i in 0:Array.size(state)
|
for i in 0:Array.size(state)
|
||||||
if Array.nth(state, i)
|
if Array.nth(state, i)
|
||||||
o = String.concat(o, "#")
|
String.set(out, i, String.nth("#", 0))
|
||||||
else
|
else
|
||||||
o = String.concat(o, " ")
|
String.set(out, i, String.nth(" ", 0))
|
||||||
return o
|
return out
|
||||||
|
|
||||||
func main[] : I64
|
func main[] : I64
|
||||||
let SIZE: I64 = 60
|
let SIZE: I64 = 60
|
||||||
|
|||||||
116
src/builtin.s
116
src/builtin.s
@@ -1,116 +0,0 @@
|
|||||||
String.nth:
|
|
||||||
movzx rax, byte [rdi + rsi]
|
|
||||||
ret
|
|
||||||
|
|
||||||
String.set:
|
|
||||||
mov [rdi + rsi], dl
|
|
||||||
ret
|
|
||||||
|
|
||||||
OS.time:
|
|
||||||
push rbx
|
|
||||||
sub rsp, 16
|
|
||||||
mov rbx, rsp
|
|
||||||
mov rdi, rbx
|
|
||||||
xor esi, esi
|
|
||||||
call gettimeofday
|
|
||||||
imul rcx, qword [rbx], 1000
|
|
||||||
mov rax, qword [rbx+8]
|
|
||||||
mov esi, 1000
|
|
||||||
cqo
|
|
||||||
idiv rsi
|
|
||||||
add rax, rcx
|
|
||||||
add rsp, 16
|
|
||||||
pop rbx
|
|
||||||
ret
|
|
||||||
|
|
||||||
OS.listdir:
|
|
||||||
push r14
|
|
||||||
push rbx
|
|
||||||
push rax
|
|
||||||
mov r14, rdi
|
|
||||||
call Array.new
|
|
||||||
mov rbx, rax
|
|
||||||
mov rdi, r14
|
|
||||||
call opendir
|
|
||||||
mov r14, rax
|
|
||||||
.OS.listdir.1:
|
|
||||||
mov rdi, r14
|
|
||||||
call readdir
|
|
||||||
test rax, rax
|
|
||||||
je .OS.listdir.3
|
|
||||||
cmp byte [rax+19], 46
|
|
||||||
jne .OS.listdir.2
|
|
||||||
movzx ecx, byte [rax+20]
|
|
||||||
test ecx, ecx
|
|
||||||
je .OS.listdir.1
|
|
||||||
cmp ecx, 46
|
|
||||||
jne .OS.listdir.2
|
|
||||||
cmp byte [rax+21], 0
|
|
||||||
je .OS.listdir.1
|
|
||||||
.OS.listdir.2:
|
|
||||||
add rax, 19
|
|
||||||
mov rdi, rax
|
|
||||||
call strdup
|
|
||||||
mov rsi, rax
|
|
||||||
mov rdi, rbx
|
|
||||||
call Array.push
|
|
||||||
jmp .OS.listdir.1
|
|
||||||
.OS.listdir.3:
|
|
||||||
mov rdi, r14
|
|
||||||
call closedir
|
|
||||||
mov rax, rbx
|
|
||||||
add rsp, 8
|
|
||||||
pop rbx
|
|
||||||
pop r14
|
|
||||||
ret
|
|
||||||
|
|
||||||
Array.nth:
|
|
||||||
mov rax, [rdi]
|
|
||||||
mov rax, [rax + rsi*8]
|
|
||||||
ret
|
|
||||||
|
|
||||||
Array.set:
|
|
||||||
mov rax, [rdi]
|
|
||||||
mov [rax + rsi*8], rdx
|
|
||||||
ret
|
|
||||||
|
|
||||||
Array.push:
|
|
||||||
push r14
|
|
||||||
push rbx
|
|
||||||
push rax
|
|
||||||
mov r14, rsi
|
|
||||||
mov rbx, rdi
|
|
||||||
mov rax, [rdi]
|
|
||||||
mov rcx, [rdi + 16]
|
|
||||||
cmp rcx, [rdi + 8]
|
|
||||||
jne .Array.push.1
|
|
||||||
lea rdx, [rcx + rcx]
|
|
||||||
mov rsi, 4
|
|
||||||
test rcx, rcx
|
|
||||||
cmovnz rsi, rdx
|
|
||||||
mov [rbx + 8], rsi
|
|
||||||
shl rsi, 3
|
|
||||||
mov rdi, rax
|
|
||||||
call realloc
|
|
||||||
mov [rbx], rax
|
|
||||||
mov rcx, [rbx + 16]
|
|
||||||
.Array.push.1:
|
|
||||||
mov [rax + rcx*8], r14
|
|
||||||
inc qword [rbx + 16]
|
|
||||||
add rsp, 8
|
|
||||||
pop rbx
|
|
||||||
pop r14
|
|
||||||
ret
|
|
||||||
|
|
||||||
Array.size:
|
|
||||||
mov rax, [rdi + 16]
|
|
||||||
ret
|
|
||||||
|
|
||||||
Array.free:
|
|
||||||
push rbx
|
|
||||||
mov rbx, rdi
|
|
||||||
mov rdi, [rdi]
|
|
||||||
call free
|
|
||||||
mov rdi, rbx
|
|
||||||
pop rbx
|
|
||||||
jmp free
|
|
||||||
@@ -95,7 +95,9 @@ impl CodegenX86_64 {
|
|||||||
pub fn emit_prologue(&mut self) -> Result<(), ZernError> {
|
pub fn emit_prologue(&mut self) -> Result<(), ZernError> {
|
||||||
emit!(
|
emit!(
|
||||||
&mut self.output,
|
&mut self.output,
|
||||||
"
|
"section .note.GNU-stack
|
||||||
|
db 0
|
||||||
|
|
||||||
section .text
|
section .text
|
||||||
extern malloc
|
extern malloc
|
||||||
extern calloc
|
extern calloc
|
||||||
@@ -124,15 +126,125 @@ extern readdir
|
|||||||
extern closedir
|
extern closedir
|
||||||
extern exit
|
extern exit
|
||||||
extern gettimeofday
|
extern gettimeofday
|
||||||
",
|
|
||||||
);
|
|
||||||
emit!(&mut self.output, "{}", include_str!("builtin.s"));
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn emit_epilogue(&mut self) -> Result<(), ZernError> {
|
String.nth:
|
||||||
emit!(&mut self.output, "section .note.GNU-stack");
|
movzx rax, byte [rdi + rsi]
|
||||||
emit!(&mut self.output, " db 0");
|
ret
|
||||||
|
|
||||||
|
String.set:
|
||||||
|
mov [rdi + rsi], dl
|
||||||
|
ret
|
||||||
|
|
||||||
|
OS.time:
|
||||||
|
push rbx
|
||||||
|
sub rsp, 16
|
||||||
|
mov rbx, rsp
|
||||||
|
mov rdi, rbx
|
||||||
|
xor esi, esi
|
||||||
|
call gettimeofday
|
||||||
|
imul rcx, qword [rbx], 1000
|
||||||
|
mov rax, qword [rbx+8]
|
||||||
|
mov esi, 1000
|
||||||
|
cqo
|
||||||
|
idiv rsi
|
||||||
|
add rax, rcx
|
||||||
|
add rsp, 16
|
||||||
|
pop rbx
|
||||||
|
ret
|
||||||
|
|
||||||
|
OS.listdir:
|
||||||
|
push r14
|
||||||
|
push rbx
|
||||||
|
push rax
|
||||||
|
mov r14, rdi
|
||||||
|
call Array.new
|
||||||
|
mov rbx, rax
|
||||||
|
mov rdi, r14
|
||||||
|
call opendir
|
||||||
|
mov r14, rax
|
||||||
|
.OS.listdir.1:
|
||||||
|
mov rdi, r14
|
||||||
|
call readdir
|
||||||
|
test rax, rax
|
||||||
|
je .OS.listdir.3
|
||||||
|
cmp byte [rax+19], 46
|
||||||
|
jne .OS.listdir.2
|
||||||
|
movzx ecx, byte [rax+20]
|
||||||
|
test ecx, ecx
|
||||||
|
je .OS.listdir.1
|
||||||
|
cmp ecx, 46
|
||||||
|
jne .OS.listdir.2
|
||||||
|
cmp byte [rax+21], 0
|
||||||
|
je .OS.listdir.1
|
||||||
|
.OS.listdir.2:
|
||||||
|
add rax, 19
|
||||||
|
mov rdi, rax
|
||||||
|
call strdup
|
||||||
|
mov rsi, rax
|
||||||
|
mov rdi, rbx
|
||||||
|
call Array.push
|
||||||
|
jmp .OS.listdir.1
|
||||||
|
.OS.listdir.3:
|
||||||
|
mov rdi, r14
|
||||||
|
call closedir
|
||||||
|
mov rax, rbx
|
||||||
|
add rsp, 8
|
||||||
|
pop rbx
|
||||||
|
pop r14
|
||||||
|
ret
|
||||||
|
|
||||||
|
Array.nth:
|
||||||
|
mov rax, [rdi]
|
||||||
|
mov rax, [rax + rsi*8]
|
||||||
|
ret
|
||||||
|
|
||||||
|
Array.set:
|
||||||
|
mov rax, [rdi]
|
||||||
|
mov [rax + rsi*8], rdx
|
||||||
|
ret
|
||||||
|
|
||||||
|
Array.push:
|
||||||
|
push r14
|
||||||
|
push rbx
|
||||||
|
push rax
|
||||||
|
mov r14, rsi
|
||||||
|
mov rbx, rdi
|
||||||
|
mov rax, [rdi]
|
||||||
|
mov rcx, [rdi + 16]
|
||||||
|
cmp rcx, [rdi + 8]
|
||||||
|
jne .Array.push.1
|
||||||
|
lea rdx, [rcx + rcx]
|
||||||
|
mov rsi, 4
|
||||||
|
test rcx, rcx
|
||||||
|
cmovnz rsi, rdx
|
||||||
|
mov [rbx + 8], rsi
|
||||||
|
shl rsi, 3
|
||||||
|
mov rdi, rax
|
||||||
|
call realloc
|
||||||
|
mov [rbx], rax
|
||||||
|
mov rcx, [rbx + 16]
|
||||||
|
.Array.push.1:
|
||||||
|
mov [rax + rcx*8], r14
|
||||||
|
inc qword [rbx + 16]
|
||||||
|
add rsp, 8
|
||||||
|
pop rbx
|
||||||
|
pop r14
|
||||||
|
ret
|
||||||
|
|
||||||
|
Array.size:
|
||||||
|
mov rax, [rdi + 16]
|
||||||
|
ret
|
||||||
|
|
||||||
|
Array.free:
|
||||||
|
push rbx
|
||||||
|
mov rbx, rdi
|
||||||
|
mov rdi, [rdi]
|
||||||
|
call free
|
||||||
|
mov rdi, rbx
|
||||||
|
pop rbx
|
||||||
|
jmp free
|
||||||
|
"
|
||||||
|
);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -220,8 +332,9 @@ extern gettimeofday
|
|||||||
|
|
||||||
self.compile_stmt(env, *body)?;
|
self.compile_stmt(env, *body)?;
|
||||||
|
|
||||||
// TODO: default exit code only for main
|
if name.lexeme == "main" {
|
||||||
emit!(&mut self.output, " mov rax, 0");
|
emit!(&mut self.output, " mov rax, 0");
|
||||||
|
}
|
||||||
|
|
||||||
emit!(&mut self.output, " mov rsp, rbp");
|
emit!(&mut self.output, " mov rsp, rbp");
|
||||||
emit!(&mut self.output, " pop rbp");
|
emit!(&mut self.output, " pop rbp");
|
||||||
|
|||||||
@@ -42,7 +42,6 @@ fn compile_file(path: String) -> Result<(), ZernError> {
|
|||||||
codegen.emit_prologue()?;
|
codegen.emit_prologue()?;
|
||||||
compile_file_to(&mut codegen, "std.zr", include_str!("std.zr").into())?;
|
compile_file_to(&mut codegen, "std.zr", include_str!("std.zr").into())?;
|
||||||
compile_file_to(&mut codegen, filename, source)?;
|
compile_file_to(&mut codegen, filename, source)?;
|
||||||
codegen.emit_epilogue()?;
|
|
||||||
|
|
||||||
// TODO
|
// TODO
|
||||||
if fs::write("out.s", codegen.get_output()).is_err() {
|
if fs::write("out.s", codegen.get_output()).is_err() {
|
||||||
|
|||||||
@@ -103,7 +103,6 @@ impl Parser {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: synchronization after parse error
|
|
||||||
if self.match_token(&[TokenType::KeywordLet]) {
|
if self.match_token(&[TokenType::KeywordLet]) {
|
||||||
self.let_declaration()
|
self.let_declaration()
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
21
src/std.zr
21
src/std.zr
@@ -1,12 +1,18 @@
|
|||||||
func panic[msg: String] : I64
|
func panic[msg: String] : I64
|
||||||
printf("PANIC: %s\n", msg)
|
printf("PANIC: %s\n", msg)
|
||||||
exit(1)
|
exit(1)
|
||||||
|
return 0
|
||||||
|
|
||||||
func print[x: String] : I64
|
func print[x: String] : I64
|
||||||
printf("%s\n", x)
|
printf("%s\n", x)
|
||||||
|
return 0
|
||||||
|
|
||||||
func print_i64[x: I64] : I64
|
func print_i64[x: I64] : I64
|
||||||
printf("%ld\n", x)
|
printf("%ld\n", x)
|
||||||
|
return 0
|
||||||
|
|
||||||
|
func String.is_whitespace[c: Char] : Bool
|
||||||
|
return c == 10 || c == 32 || c == 13 || c == 9
|
||||||
|
|
||||||
func String.concat[a: String, b: String] : String
|
func String.concat[a: String, b: String] : String
|
||||||
let c: String = malloc(strlen(a) + strlen(b) + 1)
|
let c: String = malloc(strlen(a) + strlen(b) + 1)
|
||||||
@@ -19,6 +25,18 @@ func String.substr[s: String, start: I64, length: I64] : String
|
|||||||
strlcpy(out, s + start, length + 1)
|
strlcpy(out, s + start, length + 1)
|
||||||
return out
|
return out
|
||||||
|
|
||||||
|
func String.trim[s: String] : String
|
||||||
|
let start: I64 = 0
|
||||||
|
let end: I64 = strlen(s) - 1
|
||||||
|
|
||||||
|
while start <= end && String.is_whitespace(String.nth(s, start))
|
||||||
|
start = start + 1
|
||||||
|
|
||||||
|
while end >= start && String.is_whitespace(String.nth(s, end))
|
||||||
|
end = end - 1
|
||||||
|
|
||||||
|
return String.substr(s, start, end - start + 1)
|
||||||
|
|
||||||
func String.rev[s: String] : String
|
func String.rev[s: String] : String
|
||||||
let len: I64 = strlen(s)
|
let len: I64 = strlen(s)
|
||||||
let out: String = malloc(len + 1)
|
let out: String = malloc(len + 1)
|
||||||
@@ -52,8 +70,9 @@ func IO.write_file[path: String, content: String] : I64
|
|||||||
|
|
||||||
fwrite(content, 1, strlen(content), file)
|
fwrite(content, 1, strlen(content), file)
|
||||||
fclose(file)
|
fclose(file)
|
||||||
|
return 0
|
||||||
|
|
||||||
func Char.to_i64[c: Char]: I64
|
func Char.parse_i64[c: Char]: I64
|
||||||
return c - 48
|
return c - 48
|
||||||
|
|
||||||
func I64.to_string[n: I64] : String
|
func I64.to_string[n: I64] : String
|
||||||
|
|||||||
1
test.zr
1
test.zr
@@ -16,6 +16,7 @@ func run_test[x: String] : I64
|
|||||||
let run_end_time: I64 = OS.time()
|
let run_end_time: I64 = OS.time()
|
||||||
|
|
||||||
printf("\033[93mRunning %s...\033[0m %ldms\n", x, run_end_time - run_start_time)
|
printf("\033[93mRunning %s...\033[0m %ldms\n", x, run_end_time - run_start_time)
|
||||||
|
return 0
|
||||||
|
|
||||||
func main[] : I64
|
func main[] : I64
|
||||||
system("cargo build --release")
|
system("cargo build --release")
|
||||||
|
|||||||
Reference in New Issue
Block a user