hex, base64, Math.urandom, IO.read_line
This commit is contained in:
14
examples/guess_number.zr
Normal file
14
examples/guess_number.zr
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
func main[] : I64
|
||||||
|
let answer: I64 = Math.abs(Math.urandom()) % 100
|
||||||
|
|
||||||
|
while true
|
||||||
|
print("Guess a number: ")
|
||||||
|
let guess: I64 = IO.read_line() |> String.trim() |> I64.parse()
|
||||||
|
|
||||||
|
if guess == answer
|
||||||
|
print("You win!")
|
||||||
|
return 0
|
||||||
|
else if guess < answer
|
||||||
|
print("Too low!")
|
||||||
|
else
|
||||||
|
print("Too high!")
|
||||||
@@ -74,7 +74,7 @@ impl CodegenX86_64 {
|
|||||||
output: String::new(),
|
output: String::new(),
|
||||||
data_section: String::new(),
|
data_section: String::new(),
|
||||||
label_counter: 0,
|
label_counter: 0,
|
||||||
data_counter: 0,
|
data_counter: 1,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -86,7 +86,7 @@ impl CodegenX86_64 {
|
|||||||
pub fn get_output(&self) -> String {
|
pub fn get_output(&self) -> String {
|
||||||
format!(
|
format!(
|
||||||
"section .data
|
"section .data
|
||||||
SASSERT db \"assertion failed on line %d\",10,0
|
S0 db \"assertion failed on line %d\",10,0
|
||||||
{}{}",
|
{}{}",
|
||||||
self.data_section, self.output
|
self.data_section, self.output
|
||||||
)
|
)
|
||||||
@@ -99,6 +99,7 @@ impl CodegenX86_64 {
|
|||||||
db 0
|
db 0
|
||||||
|
|
||||||
section .text
|
section .text
|
||||||
|
extern stdin
|
||||||
extern malloc
|
extern malloc
|
||||||
extern calloc
|
extern calloc
|
||||||
extern realloc
|
extern realloc
|
||||||
@@ -112,6 +113,7 @@ extern strcat
|
|||||||
extern strcpy
|
extern strcpy
|
||||||
extern strdup
|
extern strdup
|
||||||
extern strlcpy
|
extern strlcpy
|
||||||
|
extern fgets
|
||||||
extern fopen
|
extern fopen
|
||||||
extern fseek
|
extern fseek
|
||||||
extern ftell
|
extern ftell
|
||||||
@@ -126,6 +128,16 @@ extern closedir
|
|||||||
extern exit
|
extern exit
|
||||||
extern gettimeofday
|
extern gettimeofday
|
||||||
|
|
||||||
|
section .text.deref
|
||||||
|
deref:
|
||||||
|
mov rax, qword [rdi]
|
||||||
|
ret
|
||||||
|
|
||||||
|
section .text.IO.stdin
|
||||||
|
IO.stdin:
|
||||||
|
mov rax, [rel stdin]
|
||||||
|
ret
|
||||||
|
|
||||||
section .text.Bit.lshift
|
section .text.Bit.lshift
|
||||||
Bit.lshift:
|
Bit.lshift:
|
||||||
mov rcx, rsi
|
mov rcx, rsi
|
||||||
@@ -386,7 +398,7 @@ Array.free:
|
|||||||
let skip_label = self.label();
|
let skip_label = self.label();
|
||||||
emit!(&mut self.output, " test rax, rax");
|
emit!(&mut self.output, " test rax, rax");
|
||||||
emit!(&mut self.output, " jne {}", skip_label);
|
emit!(&mut self.output, " jne {}", skip_label);
|
||||||
emit!(&mut self.output, " mov rdi, SASSERT");
|
emit!(&mut self.output, " mov rdi, S0");
|
||||||
emit!(&mut self.output, " mov rsi, {}", keyword.loc.line);
|
emit!(&mut self.output, " mov rsi, {}", keyword.loc.line);
|
||||||
emit!(&mut self.output, " call printf");
|
emit!(&mut self.output, " call printf");
|
||||||
emit!(&mut self.output, " mov rdi, 1");
|
emit!(&mut self.output, " mov rdi, 1");
|
||||||
@@ -605,6 +617,7 @@ Array.free:
|
|||||||
emit!(&mut self.output, " call Array.new");
|
emit!(&mut self.output, " call Array.new");
|
||||||
emit!(&mut self.output, " mov r12, rax");
|
emit!(&mut self.output, " mov r12, rax");
|
||||||
|
|
||||||
|
// TODO: nested array literals probably dont work
|
||||||
for expr in exprs {
|
for expr in exprs {
|
||||||
self.compile_expr(env, expr)?;
|
self.compile_expr(env, expr)?;
|
||||||
emit!(&mut self.output, " mov rsi, rax");
|
emit!(&mut self.output, " mov rsi, rax");
|
||||||
|
|||||||
102
src/std.zr
102
src/std.zr
@@ -52,6 +52,11 @@ func String.rev[s: String] : String
|
|||||||
String.set(out, len, 0)
|
String.set(out, len, 0)
|
||||||
return out
|
return out
|
||||||
|
|
||||||
|
func IO.read_line[]: String
|
||||||
|
let buffer: String = malloc(1024)
|
||||||
|
fgets(buffer, 1024, IO.stdin())
|
||||||
|
return buffer
|
||||||
|
|
||||||
func IO.read_file[path: String]: String
|
func IO.read_file[path: String]: String
|
||||||
let file: Ptr = fopen(path, "rb")
|
let file: Ptr = fopen(path, "rb")
|
||||||
if !file
|
if !file
|
||||||
@@ -149,10 +154,64 @@ func Math.is_prime[n: I64]: I64
|
|||||||
i = i + 6
|
i = i + 6
|
||||||
return true
|
return true
|
||||||
|
|
||||||
|
func Math.urandom[]: I64
|
||||||
|
let buffer: Ptr = malloc(8)
|
||||||
|
let file: Ptr = fopen("/dev/urandom", "r")
|
||||||
|
fread(buffer, 8, 1, file)
|
||||||
|
fclose(file)
|
||||||
|
let n: I64 = deref(buffer)
|
||||||
|
free(buffer)
|
||||||
|
return n
|
||||||
|
|
||||||
func Array.new[] : Array
|
func Array.new[] : Array
|
||||||
return calloc(1, 24)
|
return calloc(1, 24)
|
||||||
|
|
||||||
func Math.Crypto.rc4[key: String, plaintext: String]: String
|
func Crypto.hex_encode[s: String] : String
|
||||||
|
let hex_chars: String = "0123456789abcdef"
|
||||||
|
let s_len: I64 = strlen(s)
|
||||||
|
let j: I64 = 0
|
||||||
|
let out: String = malloc(s_len*2+1)
|
||||||
|
|
||||||
|
for i in 0..s_len
|
||||||
|
let high: U8 = Bit.and(Bit.rshift(String.nth(s, i), 4), 15)
|
||||||
|
let low: U8 = Bit.and(String.nth(s, i), 15)
|
||||||
|
String.set(out, j, String.nth(hex_chars, high))
|
||||||
|
String.set(out, j+1, String.nth(hex_chars, low))
|
||||||
|
j = j + 2
|
||||||
|
|
||||||
|
String.set(out, j, 0)
|
||||||
|
return out
|
||||||
|
|
||||||
|
func Crypto.from_hex_digit[d: U8] : I64
|
||||||
|
if d == 97
|
||||||
|
return 10
|
||||||
|
if d == 98
|
||||||
|
return 11
|
||||||
|
if d == 99
|
||||||
|
return 12
|
||||||
|
if d == 100
|
||||||
|
return 13
|
||||||
|
if d == 101
|
||||||
|
return 14
|
||||||
|
if d == 102
|
||||||
|
return 15
|
||||||
|
return U8.parse_i64(d)
|
||||||
|
|
||||||
|
func Crypto.hex_decode[s: String] : String
|
||||||
|
let s_len: I64 = strlen(s)
|
||||||
|
let i: I64 = 0
|
||||||
|
let j: I64 = 0
|
||||||
|
let out: String = malloc(s_len/2+1)
|
||||||
|
|
||||||
|
while i < s_len
|
||||||
|
String.set(out, j, Crypto.from_hex_digit(String.nth(s, i)) * 16 + Crypto.from_hex_digit(String.nth(s, i+1)))
|
||||||
|
i = i + 2
|
||||||
|
j = j + 1
|
||||||
|
|
||||||
|
String.set(out, j, 0)
|
||||||
|
return out
|
||||||
|
|
||||||
|
func Crypto.rc4[key: String, plaintext: String]: String
|
||||||
let S: String = malloc(256)
|
let S: String = malloc(256)
|
||||||
for i in 0..256
|
for i in 0..256
|
||||||
String.set(S, i, i)
|
String.set(S, i, i)
|
||||||
@@ -184,7 +243,7 @@ func Math.Crypto.rc4[key: String, plaintext: String]: String
|
|||||||
free(S)
|
free(S)
|
||||||
return ciphertext
|
return ciphertext
|
||||||
|
|
||||||
func Math.Crypto.base64_encode[s: String] : String
|
func Crypto.base64_encode[s: String] : String
|
||||||
let chars: String = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
|
let chars: String = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
|
||||||
let s_len: I64 = strlen(s)
|
let s_len: I64 = strlen(s)
|
||||||
let output: String = malloc(s_len*2)
|
let output: String = malloc(s_len*2)
|
||||||
@@ -217,4 +276,41 @@ func Math.Crypto.base64_encode[s: String] : String
|
|||||||
String.set(output, j-1, equals)
|
String.set(output, j-1, equals)
|
||||||
|
|
||||||
String.set(output, j, 0)
|
String.set(output, j, 0)
|
||||||
return output
|
return output
|
||||||
|
|
||||||
|
func Crypto.base64_decode[s: String] : String
|
||||||
|
let chars: String = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
|
||||||
|
let s_len: I64 = strlen(s)
|
||||||
|
let out: String = malloc(s_len)
|
||||||
|
let i: I64 = 0
|
||||||
|
let j: I64 = 0
|
||||||
|
|
||||||
|
while String.nth(s, s_len-1) == 61
|
||||||
|
s_len = s_len - 1
|
||||||
|
|
||||||
|
while i < s_len
|
||||||
|
let s1: U8 = String.find(chars, String.nth(s, i))
|
||||||
|
let s2: U8 = 0
|
||||||
|
if i + 1 < s_len
|
||||||
|
s2 = String.find(chars, String.nth(s, i+1))
|
||||||
|
let s3: U8 = 0
|
||||||
|
if i + 2 < s_len
|
||||||
|
s3 = String.find(chars, String.nth(s, i+2))
|
||||||
|
let s4: U8 = 0
|
||||||
|
if i + 3 < s_len
|
||||||
|
s4 = String.find(chars, String.nth(s, i+3))
|
||||||
|
i = i + 4
|
||||||
|
|
||||||
|
let triple: U8 = Bit.or(Bit.or(Bit.or(Bit.lshift(s1, 18), Bit.lshift(s2, 12)), Bit.lshift(s3, 6)), s4)
|
||||||
|
|
||||||
|
String.set(out, j, Bit.and(Bit.rshift(triple, 16), 255))
|
||||||
|
j = j + 1
|
||||||
|
if s3 != 64
|
||||||
|
String.set(out, j, Bit.and(Bit.rshift(triple, 8), 255))
|
||||||
|
j = j + 1
|
||||||
|
if s4 != 64
|
||||||
|
String.set(out, j, Bit.and(triple, 255))
|
||||||
|
j = j + 1
|
||||||
|
|
||||||
|
String.set(out, j, 0)
|
||||||
|
return out
|
||||||
@@ -231,7 +231,7 @@ impl Tokenizer {
|
|||||||
self.handle_indentation()?;
|
self.handle_indentation()?;
|
||||||
}
|
}
|
||||||
'0'..='9' => self.scan_number(),
|
'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"),
|
_ => return error!(self.loc, "unexpected character"),
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|||||||
Reference in New Issue
Block a user