std
This commit is contained in:
@@ -2,6 +2,11 @@
|
||||
|
||||
A very cool language
|
||||
|
||||
## Huh?
|
||||
* Indentation-based syntax
|
||||
* Compiled to x86_64 Assembly
|
||||
* Sometimes works
|
||||
|
||||
## Syntax
|
||||
```go
|
||||
func fib[n: I64] : I64
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
func print_i64[x: I64] : I64
|
||||
printf("%ld\n", x)
|
||||
|
||||
func main[] : I64
|
||||
let sum: I64 = 0
|
||||
|
||||
|
||||
@@ -1,27 +1,9 @@
|
||||
func print_i64[x: I64] : I64
|
||||
printf("%ld\n", x)
|
||||
|
||||
func is_prime[n: I64]: I64
|
||||
if n <= 1
|
||||
return false
|
||||
if n == 2 || n == 3
|
||||
return true
|
||||
if n % 2 == 0 || n % 3 == 0
|
||||
return false
|
||||
|
||||
let i: I64 = 5
|
||||
while i * i <= n
|
||||
if n % i == 0 || n % (i + 2) == 0
|
||||
return false
|
||||
i = i + 6
|
||||
return true
|
||||
|
||||
func main[] : I64
|
||||
let sum: I64 = 0
|
||||
|
||||
let i: I64 = 0
|
||||
while i < 2000000
|
||||
if is_prime(i)
|
||||
if Math.is_prime(i)
|
||||
sum = sum + i
|
||||
i = i + 1
|
||||
print_i64(sum)
|
||||
@@ -1,6 +1,3 @@
|
||||
func print_i64[x: I64] : I64
|
||||
printf("%ld\n", x)
|
||||
|
||||
func num_divisors[n: I64] : I64
|
||||
let end: I64 = isqrt(n)
|
||||
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
func print_i64[x: I64] : I64
|
||||
printf("%ld\n", x)
|
||||
|
||||
func collatz_num[n: I64] : I64
|
||||
if n % 2 == 0
|
||||
return n / 2
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
func print_i64[x: I64] : I64
|
||||
printf("%ld\n", x)
|
||||
|
||||
func main[] : I64
|
||||
let sum: I64 = 0
|
||||
let a: I64 = 0
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
func print_i64[x: I64] : I64
|
||||
printf("%ld\n", x)
|
||||
|
||||
func main[] : I64
|
||||
let n: I64 = 600851475143
|
||||
let f: I64 = 2
|
||||
|
||||
@@ -1,11 +1,3 @@
|
||||
func print_i64[x: I64] : I64
|
||||
printf("%ld\n", x)
|
||||
|
||||
func I64.to_string[n: I64] : String
|
||||
let x: I64 = malloc(21)
|
||||
sprintf(x, "%ld", n)
|
||||
return x
|
||||
|
||||
func main[] : I64
|
||||
let out: I64 = 0
|
||||
|
||||
|
||||
@@ -1,21 +1,8 @@
|
||||
func print_i64[x: I64] : I64
|
||||
printf("%ld\n", x)
|
||||
|
||||
func gcd[a: I64, b: I64] : I64
|
||||
while b != 0
|
||||
let tmp: I64 = b
|
||||
b = a % b
|
||||
a = tmp
|
||||
return a
|
||||
|
||||
func lcm[a: I64, b: I64] : I64
|
||||
return (a * b) / gcd(a, b)
|
||||
|
||||
func main[] : I64
|
||||
let out: I64 = 1
|
||||
|
||||
let i: I64 = 1
|
||||
while i < 21
|
||||
out = lcm(out, i)
|
||||
out = Math.lcm(out, i)
|
||||
i = i + 1
|
||||
print_i64(out)
|
||||
@@ -1,6 +1,3 @@
|
||||
func print_i64[x: I64] : I64
|
||||
printf("%ld\n", x)
|
||||
|
||||
func main[] : I64
|
||||
let sum_of_squares: I64 = 0
|
||||
let i: I64 = 1
|
||||
|
||||
@@ -1,27 +1,9 @@
|
||||
func print_i64[x: I64] : I64
|
||||
printf("%ld\n", x)
|
||||
|
||||
func is_prime[n: I64]: I64
|
||||
if n <= 1
|
||||
return false
|
||||
if n == 2 || n == 3
|
||||
return true
|
||||
if n % 2 == 0 || n % 3 == 0
|
||||
return false
|
||||
|
||||
let i: I64 = 5
|
||||
while i * i <= n
|
||||
if n % i == 0 || n % (i + 2) == 0
|
||||
return false
|
||||
i = i + 6
|
||||
return true
|
||||
|
||||
func main[] : I64
|
||||
let found: I64 = 0
|
||||
|
||||
let i: I64 = 1
|
||||
while 1
|
||||
if is_prime(i)
|
||||
if Math.is_prime(i)
|
||||
found = found + 1
|
||||
if found == 10001
|
||||
print_i64(i)
|
||||
|
||||
@@ -1,9 +1,3 @@
|
||||
func print_i64[x: I64] : I64
|
||||
printf("%ld\n", x)
|
||||
|
||||
func char_to_i64[c: I64]: I64
|
||||
return c - 48
|
||||
|
||||
func main[] : I64
|
||||
let n: String = "7316717653133062491922511967442657474235534919493496983520312774506326239578318016984801869478851843858615607891129494954595017379583319528532088055111254069874715852386305071569329096329522744304355766896648950445244523161731856403098711121722383113622298934233803081353362766142828064444866452387493035890729629049156044077239071381051585930796086670172427121883998797908792274921901699720888093776657273330010533678812202354218097512545405947522435258490771167055601360483958644670632441572215539753697817977846174064955149290862569321978468622482839722413756570560574902614079729686524145351004748216637048440319989000889524345065854122758866688116427171479924442928230863465674813919123162824586178664583591245665294765456828489128831426076900422421902267105562632111110937054421750694165896040807198403850962455444362981230987879927244284909188845801561660979191338754992005240636899125607176060588611646710940507754100225698315520005593572972571636269561882670428252483600823257530420752963450"
|
||||
|
||||
@@ -14,7 +8,7 @@ func main[] : I64
|
||||
let s: I64 = 1
|
||||
let j: I64 = 0
|
||||
while j < 13
|
||||
s = s * char_to_i64(nth(n, i + j))
|
||||
s = s * Char.to_i64(nth(n, i + j))
|
||||
j = j + 1
|
||||
if s > out
|
||||
out = s
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
func print_i64[x: I64] : I64
|
||||
printf("%ld\n", x)
|
||||
|
||||
func main[] : I64
|
||||
let a: I64 = 1
|
||||
while a < 1000
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
func print_i64[x: I64] : I64
|
||||
printf("%ld\n", x)
|
||||
|
||||
func main[] : I64
|
||||
let a: I64 = 0
|
||||
let b: I64 = 1
|
||||
|
||||
@@ -1,12 +1,7 @@
|
||||
func print_i64[x: I64] : I64
|
||||
printf("%ld\n", x)
|
||||
|
||||
func I64.to_string[n: I64] : String
|
||||
let x: String = malloc(21)
|
||||
sprintf(x, "%ld", n)
|
||||
return x
|
||||
|
||||
func main[] : I64
|
||||
let s: String = I64.to_string(58394)
|
||||
print_i64(strlen(s))
|
||||
free(s)
|
||||
let a: String = I64.to_string(58394)
|
||||
print_i64(strlen(a))
|
||||
let b: String = concat(a, "test")
|
||||
print_i64(strlen(b))
|
||||
free(a)
|
||||
free(b)
|
||||
@@ -101,11 +101,14 @@ extern printf
|
||||
extern sprintf
|
||||
extern strlen
|
||||
extern strcmp
|
||||
extern strcat
|
||||
extern strcpy
|
||||
extern strdup
|
||||
extern puts
|
||||
extern system
|
||||
print equ puts
|
||||
extern exit
|
||||
copystr equ strdup
|
||||
|
||||
; generated with clang
|
||||
strrev:
|
||||
push r14
|
||||
push rbx
|
||||
@@ -118,15 +121,15 @@ strrev:
|
||||
mov rcx, rax
|
||||
mov rsi, r14
|
||||
mov rdx, r14
|
||||
.LBB0_1:
|
||||
.strrev.1:
|
||||
sub rdx, 1
|
||||
jb .LBB0_2
|
||||
jb .strrev.2
|
||||
mov sil, byte [rbx + rsi - 1]
|
||||
mov byte [rcx], sil
|
||||
inc rcx
|
||||
mov rsi, rdx
|
||||
jmp .LBB0_1
|
||||
.LBB0_2:
|
||||
jmp .strrev.1
|
||||
.strrev.2:
|
||||
mov byte [rax + r14], 0
|
||||
add rsp, 8
|
||||
pop rbx
|
||||
@@ -138,30 +141,30 @@ isqrt:
|
||||
mov rcx, 1
|
||||
mov rbx, rdi
|
||||
shl rcx, 62
|
||||
.LBB0_3:
|
||||
.isqrt.1:
|
||||
cmp rcx, 0
|
||||
je .LBB0_5
|
||||
je .isqrt.5
|
||||
cmp rcx, rbx
|
||||
jbe .LBB0_4
|
||||
jbe .isqrt.2
|
||||
shr rcx, 2
|
||||
jmp .LBB0_3
|
||||
.LBB0_4:
|
||||
jmp .isqrt.1
|
||||
.isqrt.2:
|
||||
cmp rcx, 0
|
||||
je .LBB0_5
|
||||
je .isqrt.5
|
||||
mov rdx, rax
|
||||
add rdx, rcx
|
||||
cmp rbx, rdx
|
||||
jb .LBB0_7
|
||||
jb .isqrt.3
|
||||
sub rbx, rdx
|
||||
shr rax, 1
|
||||
add rax, rcx
|
||||
jmp .LBB0_6
|
||||
.LBB0_7:
|
||||
jmp .isqrt.4
|
||||
.isqrt.3:
|
||||
shr rax, 1
|
||||
.LBB0_6:
|
||||
.isqrt.4:
|
||||
shr rcx, 2
|
||||
jmp .LBB0_4
|
||||
.LBB0_5:
|
||||
jmp .isqrt.2
|
||||
.isqrt.5:
|
||||
ret
|
||||
|
||||
nth:
|
||||
@@ -259,10 +262,8 @@ nth:
|
||||
|
||||
self.compile_stmt(env, *body)?;
|
||||
|
||||
if name.lexeme == "main" {
|
||||
// default exit code
|
||||
emit!(&mut self.output, " mov rax, 0");
|
||||
}
|
||||
// TODO: default exit code only for main
|
||||
emit!(&mut self.output, " mov rax, 0");
|
||||
|
||||
emit!(&mut self.output, " mov rsp, rbp");
|
||||
emit!(&mut self.output, " pop rbp");
|
||||
@@ -356,17 +357,22 @@ nth:
|
||||
TokenType::String => {
|
||||
// TODO: actual string parsing in the tokenizer
|
||||
let value = &token.lexeme[1..token.lexeme.len() - 1].replace("\\n", "\n");
|
||||
let charcodes = value
|
||||
.chars()
|
||||
.map(|x| (x as u8).to_string())
|
||||
.collect::<Vec<String>>()
|
||||
.join(",");
|
||||
emit!(
|
||||
&mut self.data_section,
|
||||
" S{} db {},0",
|
||||
self.data_counter,
|
||||
charcodes,
|
||||
);
|
||||
|
||||
if value.is_empty() {
|
||||
emit!(&mut self.data_section, " S{} db 0", self.data_counter);
|
||||
} else {
|
||||
let charcodes = value
|
||||
.chars()
|
||||
.map(|x| (x as u8).to_string())
|
||||
.collect::<Vec<String>>()
|
||||
.join(",");
|
||||
emit!(
|
||||
&mut self.data_section,
|
||||
" S{} db {},0",
|
||||
self.data_counter,
|
||||
charcodes,
|
||||
);
|
||||
}
|
||||
emit!(&mut self.output, " mov rax, S{}", self.data_counter);
|
||||
self.data_counter += 1;
|
||||
}
|
||||
|
||||
29
src/main.rs
29
src/main.rs
@@ -10,6 +10,23 @@ use std::{
|
||||
|
||||
use tokenizer::ZernError;
|
||||
|
||||
fn compile_file_to(
|
||||
codegen: &mut codegen_x86_64::CodegenX86_64,
|
||||
filename: &str,
|
||||
source: String,
|
||||
) -> Result<(), ZernError> {
|
||||
let tokenizer = tokenizer::Tokenizer::new(filename.to_owned(), source);
|
||||
let tokens = tokenizer.tokenize()?;
|
||||
|
||||
let parser = parser::Parser::new(tokens);
|
||||
let statements = parser.parse()?;
|
||||
|
||||
for stmt in statements {
|
||||
codegen.compile_stmt(&mut codegen_x86_64::Env::new(), stmt)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn compile_file(path: String) -> Result<(), ZernError> {
|
||||
let source = match fs::read_to_string(path.clone()) {
|
||||
Ok(x) => x,
|
||||
@@ -21,18 +38,10 @@ fn compile_file(path: String) -> Result<(), ZernError> {
|
||||
|
||||
let filename = Path::new(&path).file_name().unwrap().to_str().unwrap();
|
||||
|
||||
let tokenizer = tokenizer::Tokenizer::new(filename.to_owned(), source);
|
||||
let tokens = tokenizer.tokenize()?;
|
||||
|
||||
let parser = parser::Parser::new(tokens);
|
||||
let statements = parser.parse()?;
|
||||
|
||||
let mut codegen = codegen_x86_64::CodegenX86_64::new();
|
||||
|
||||
codegen.emit_prologue()?;
|
||||
for stmt in statements {
|
||||
codegen.compile_stmt(&mut codegen_x86_64::Env::new(), stmt)?;
|
||||
}
|
||||
compile_file_to(&mut codegen, "std.zr", include_str!("std.zr").into())?;
|
||||
compile_file_to(&mut codegen, filename, source)?;
|
||||
codegen.emit_epilogue()?;
|
||||
|
||||
if fs::write("out.s", codegen.get_output()).is_err() {
|
||||
|
||||
67
src/std.zr
Normal file
67
src/std.zr
Normal file
@@ -0,0 +1,67 @@
|
||||
func print[x: String] : I64
|
||||
printf("%s\n", x)
|
||||
|
||||
func print_i64[x: I64] : I64
|
||||
printf("%ld\n", x)
|
||||
|
||||
func concat[a: String, b: String] : String
|
||||
let c: String = malloc(strlen(a) + strlen(b) + 1)
|
||||
strcpy(c, a)
|
||||
strcat(c, b)
|
||||
return c
|
||||
|
||||
func Char.to_i64[c: I64]: I64
|
||||
return c - 48
|
||||
|
||||
func I64.to_string[n: I64] : String
|
||||
let x: I64 = malloc(21)
|
||||
sprintf(x, "%ld", n)
|
||||
return x
|
||||
|
||||
func Math.gcd[a: I64, b: I64] : I64
|
||||
while b != 0
|
||||
let tmp: I64 = b
|
||||
b = a % b
|
||||
a = tmp
|
||||
return a
|
||||
|
||||
func Math.min[a: I64, b: I64] : I64
|
||||
if a < b
|
||||
return a
|
||||
return b
|
||||
|
||||
func Math.max[a: I64, b: I64] : I64
|
||||
if a > b
|
||||
return a
|
||||
return b
|
||||
|
||||
func Math.abs[n: I64] : I64
|
||||
if n < 0
|
||||
return -n
|
||||
return n
|
||||
|
||||
func Math.pow[b: I64, e: I64] : I64
|
||||
let out: I64 = 1
|
||||
let i: I64 = 0
|
||||
while i < e
|
||||
out = out * b
|
||||
i = i + 1
|
||||
return out
|
||||
|
||||
func Math.lcm[a: I64, b: I64] : I64
|
||||
return (a * b) / Math.gcd(a, b)
|
||||
|
||||
func Math.is_prime[n: I64]: I64
|
||||
if n <= 1
|
||||
return false
|
||||
if n == 2 || n == 3
|
||||
return true
|
||||
if n % 2 == 0 || n % 3 == 0
|
||||
return false
|
||||
|
||||
let i: I64 = 5
|
||||
while i * i <= n
|
||||
if n % i == 0 || n % (i + 2) == 0
|
||||
return false
|
||||
i = i + 6
|
||||
return true
|
||||
@@ -220,7 +220,7 @@ impl Tokenizer {
|
||||
self.handle_indentation()?;
|
||||
}
|
||||
'0'..='9' => self.scan_number(),
|
||||
'A'..='Z' | 'a'..='z' | '_' => self.scan_identifier(),
|
||||
'A'..='Z' | 'a'..='z' | '_' | '.' => self.scan_identifier(),
|
||||
_ => return error!(self.loc, "unexpected character"),
|
||||
}
|
||||
Ok(())
|
||||
@@ -295,7 +295,11 @@ impl Tokenizer {
|
||||
}
|
||||
|
||||
fn scan_identifier(&mut self) {
|
||||
while self.peek().is_alphanumeric() || self.peek() == '_' || self.peek() == '.' {
|
||||
while self.peek().is_alphanumeric()
|
||||
|| self.peek() == '_'
|
||||
|| self.peek() == '.'
|
||||
|| self.peek() == '!'
|
||||
{
|
||||
self.advance();
|
||||
}
|
||||
|
||||
|
||||
21
test.py
Normal file
21
test.py
Normal file
@@ -0,0 +1,21 @@
|
||||
import os
|
||||
import sys
|
||||
import time
|
||||
|
||||
os.system("cargo build --release")
|
||||
|
||||
for x in os.listdir("examples/"):
|
||||
print(
|
||||
"\033[93mBuilding %s...\033[0m" % x,
|
||||
end="",
|
||||
flush=True,
|
||||
)
|
||||
t = time.time()
|
||||
if os.system("./target/release/zern examples/" + x) != 0:
|
||||
sys.exit(1)
|
||||
print(" %sms" % round((time.time() - t) * 1000, 2))
|
||||
|
||||
t = time.time()
|
||||
if os.system("./out") != 0:
|
||||
sys.exit(1)
|
||||
print("\033[93mRunning %s...\033[0m %sms" % (x, round((time.time() - t) * 1000, 2)))
|
||||
Reference in New Issue
Block a user