use FnType instead of the tuple mess
This commit is contained in:
@@ -5,13 +5,37 @@ use crate::{
|
|||||||
tokenizer::{ZernError, error},
|
tokenizer::{ZernError, error},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
pub type Type = String;
|
||||||
|
|
||||||
pub struct StructField {
|
pub struct StructField {
|
||||||
pub offset: usize,
|
pub offset: usize,
|
||||||
pub field_type: String,
|
pub field_type: Type,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct FnType {
|
||||||
|
pub return_type: Type,
|
||||||
|
pub params: Option<Vec<Type>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FnType {
|
||||||
|
fn new(return_type: &str, params: Vec<&str>) -> FnType {
|
||||||
|
FnType {
|
||||||
|
return_type: return_type.to_string(),
|
||||||
|
params: Some(params.iter().map(|x| x.to_string()).collect()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn new_variadic(return_type: &str) -> FnType {
|
||||||
|
FnType {
|
||||||
|
return_type: return_type.to_string(),
|
||||||
|
params: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Analyzer {
|
pub struct Analyzer {
|
||||||
pub functions: HashMap<String, (String, Option<Vec<String>>)>,
|
pub functions: HashMap<String, FnType>,
|
||||||
pub constants: HashMap<String, u64>,
|
pub constants: HashMap<String, u64>,
|
||||||
pub structs: HashMap<String, HashMap<String, StructField>>,
|
pub structs: HashMap<String, HashMap<String, StructField>>,
|
||||||
}
|
}
|
||||||
@@ -20,21 +44,18 @@ impl Analyzer {
|
|||||||
pub fn new() -> Analyzer {
|
pub fn new() -> Analyzer {
|
||||||
Analyzer {
|
Analyzer {
|
||||||
functions: HashMap::from([
|
functions: HashMap::from([
|
||||||
("_builtin_heap_head".into(), ("ptr".into(), Some(vec![]))),
|
("_builtin_heap_head".into(), FnType::new("ptr", vec![])),
|
||||||
("_builtin_heap_tail".into(), ("ptr".into(), Some(vec![]))),
|
("_builtin_heap_tail".into(), FnType::new("ptr", vec![])),
|
||||||
("_builtin_err_code".into(), ("ptr".into(), Some(vec![]))),
|
("_builtin_err_code".into(), FnType::new("ptr", vec![])),
|
||||||
("_builtin_err_msg".into(), ("ptr".into(), Some(vec![]))),
|
("_builtin_err_msg".into(), FnType::new("ptr", vec![])),
|
||||||
(
|
("_builtin_read64".into(), FnType::new("i64", vec!["ptr"])),
|
||||||
"_builtin_read64".into(),
|
|
||||||
("i64".into(), Some(vec!["ptr".into()])),
|
|
||||||
),
|
|
||||||
(
|
(
|
||||||
"_builtin_set64".into(),
|
"_builtin_set64".into(),
|
||||||
("void".into(), Some(vec!["ptr".into(), "i64".into()])),
|
FnType::new("void", vec!["ptr", "any"]),
|
||||||
),
|
),
|
||||||
("_builtin_syscall".into(), ("any".into(), None)),
|
("_builtin_syscall".into(), FnType::new_variadic("any")),
|
||||||
("io.printf".into(), ("void".into(), None)),
|
("io.printf".into(), FnType::new_variadic("void")),
|
||||||
("_builtin_environ".into(), ("ptr".into(), Some(vec![]))),
|
("_builtin_environ".into(), FnType::new("ptr", vec![])),
|
||||||
]),
|
]),
|
||||||
constants: HashMap::new(),
|
constants: HashMap::new(),
|
||||||
structs: HashMap::new(),
|
structs: HashMap::new(),
|
||||||
@@ -55,10 +76,10 @@ impl Analyzer {
|
|||||||
}
|
}
|
||||||
self.functions.insert(
|
self.functions.insert(
|
||||||
name.lexeme.clone(),
|
name.lexeme.clone(),
|
||||||
(
|
FnType {
|
||||||
return_type.lexeme.clone(),
|
return_type: return_type.lexeme.clone(),
|
||||||
Some(params.iter().map(|x| x.var_type.lexeme.clone()).collect()),
|
params: Some(params.iter().map(|x| x.var_type.lexeme.clone()).collect()),
|
||||||
),
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -144,7 +165,7 @@ impl Analyzer {
|
|||||||
return error!(name.loc, format!("tried to redefine '{}'", name.lexeme));
|
return error!(name.loc, format!("tried to redefine '{}'", name.lexeme));
|
||||||
}
|
}
|
||||||
self.functions
|
self.functions
|
||||||
.insert(name.lexeme.clone(), ("any".into(), None));
|
.insert(name.lexeme.clone(), FnType::new_variadic("any"));
|
||||||
}
|
}
|
||||||
Stmt::Struct { name, fields } => {
|
Stmt::Struct { name, fields } => {
|
||||||
let mut fields_map: HashMap<String, StructField> = HashMap::new();
|
let mut fields_map: HashMap<String, StructField> = HashMap::new();
|
||||||
@@ -195,9 +216,9 @@ impl Analyzer {
|
|||||||
if let Expr::Variable(callee_name) = *callee.clone() {
|
if let Expr::Variable(callee_name) = *callee.clone() {
|
||||||
if self.functions.contains_key(&callee_name.lexeme) {
|
if self.functions.contains_key(&callee_name.lexeme) {
|
||||||
// its a function (defined/builtin/extern)
|
// its a function (defined/builtin/extern)
|
||||||
if let Some(params) = self.functions.get(&callee_name.lexeme) {
|
if let Some(fn_type) = self.functions.get(&callee_name.lexeme) {
|
||||||
// if its None, its variadic
|
// if its None, its variadic
|
||||||
if let (_, Some(params)) = params
|
if let Some(params) = &fn_type.params
|
||||||
&& params.len() != args.len()
|
&& params.len() != args.len()
|
||||||
{
|
{
|
||||||
return error!(
|
return error!(
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ func err.clear[] : void
|
|||||||
|
|
||||||
func err.set[code: i64, msg: str] : void
|
func err.set[code: i64, msg: str] : void
|
||||||
mem.write64(_builtin_err_code(), code)
|
mem.write64(_builtin_err_code(), code)
|
||||||
mem.write64(_builtin_err_msg(), msg as ptr as i64)
|
mem.write64(_builtin_err_msg(), msg)
|
||||||
|
|
||||||
func must[x: any] : any
|
func must[x: any] : any
|
||||||
if err.check()
|
if err.check()
|
||||||
@@ -57,7 +57,7 @@ func mem._split_block[blk: mem.Block, needed: i64] : void
|
|||||||
let next: mem.Block = blk->next
|
let next: mem.Block = blk->next
|
||||||
next->prev = new_blk
|
next->prev = new_blk
|
||||||
else
|
else
|
||||||
mem.write64(_builtin_heap_tail(), new_blk as ptr as i64)
|
mem.write64(_builtin_heap_tail(), new_blk)
|
||||||
|
|
||||||
blk->size = needed
|
blk->size = needed
|
||||||
blk->next = new_blk
|
blk->next = new_blk
|
||||||
@@ -87,10 +87,10 @@ func mem._request_space?[size: i64] : mem.Block
|
|||||||
tail->next = blk
|
tail->next = blk
|
||||||
blk->prev = tail
|
blk->prev = tail
|
||||||
|
|
||||||
mem.write64(_builtin_heap_tail(), blk as ptr as i64)
|
mem.write64(_builtin_heap_tail(), blk)
|
||||||
return blk
|
return blk
|
||||||
|
|
||||||
func mem.alloc?[size: i64] : ptr
|
func mem.alloc?[size: i64] : any
|
||||||
err.clear()
|
err.clear()
|
||||||
if size <= 0
|
if size <= 0
|
||||||
err.set(ERR_ALLOC_FAILED, "mem.alloc? called with non-positive size")
|
err.set(ERR_ALLOC_FAILED, "mem.alloc? called with non-positive size")
|
||||||
@@ -111,13 +111,13 @@ func mem.alloc?[size: i64] : ptr
|
|||||||
return 0
|
return 0
|
||||||
|
|
||||||
if !mem.read64(_builtin_heap_head())
|
if !mem.read64(_builtin_heap_head())
|
||||||
mem.write64(_builtin_heap_head(), blk as ptr as i64)
|
mem.write64(_builtin_heap_head(), blk)
|
||||||
|
|
||||||
mem._split_block(blk, size)
|
mem._split_block(blk, size)
|
||||||
|
|
||||||
return blk + MEM_BLOCK_SIZE
|
return blk + MEM_BLOCK_SIZE
|
||||||
|
|
||||||
func mem.alloc[size: i64] : ptr
|
func mem.alloc[size: i64] : any
|
||||||
return must(mem.alloc?(size))
|
return must(mem.alloc?(size))
|
||||||
|
|
||||||
func mem.free[x: any] : void
|
func mem.free[x: any] : void
|
||||||
@@ -137,7 +137,7 @@ func mem.free[x: any] : void
|
|||||||
let b: mem.Block = next->next
|
let b: mem.Block = next->next
|
||||||
b->prev = blk
|
b->prev = blk
|
||||||
if mem.read64(_builtin_heap_tail()) == next as ptr
|
if mem.read64(_builtin_heap_tail()) == next as ptr
|
||||||
mem.write64(_builtin_heap_tail(), blk as ptr as i64)
|
mem.write64(_builtin_heap_tail(), blk)
|
||||||
|
|
||||||
let prev: mem.Block = blk->prev
|
let prev: mem.Block = blk->prev
|
||||||
if prev as ptr && prev->free
|
if prev as ptr && prev->free
|
||||||
@@ -149,7 +149,7 @@ func mem.free[x: any] : void
|
|||||||
let b: mem.Block = blk->next
|
let b: mem.Block = blk->next
|
||||||
b->prev = prev
|
b->prev = prev
|
||||||
if mem.read64(_builtin_heap_tail()) == blk as ptr
|
if mem.read64(_builtin_heap_tail()) == blk as ptr
|
||||||
mem.write64(_builtin_heap_tail(), prev as ptr as i64)
|
mem.write64(_builtin_heap_tail(), prev)
|
||||||
blk = prev
|
blk = prev
|
||||||
|
|
||||||
let block_total: i64 = blk->size + MEM_BLOCK_SIZE
|
let block_total: i64 = blk->size + MEM_BLOCK_SIZE
|
||||||
@@ -158,12 +158,12 @@ func mem.free[x: any] : void
|
|||||||
let b: mem.Block = blk->prev
|
let b: mem.Block = blk->prev
|
||||||
b->next = blk->next
|
b->next = blk->next
|
||||||
else
|
else
|
||||||
mem.write64(_builtin_heap_head(), blk->next as ptr as i64)
|
mem.write64(_builtin_heap_head(), blk->next)
|
||||||
if blk->next
|
if blk->next
|
||||||
let b: mem.Block = blk->next
|
let b: mem.Block = blk->next
|
||||||
b->prev = blk->prev
|
b->prev = blk->prev
|
||||||
else
|
else
|
||||||
mem.write64(_builtin_heap_tail(), blk->prev as ptr as i64)
|
mem.write64(_builtin_heap_tail(), blk->prev)
|
||||||
_builtin_syscall(SYS_munmap, blk, block_total)
|
_builtin_syscall(SYS_munmap, blk, block_total)
|
||||||
|
|
||||||
func mem.realloc?[x: ptr, new_size: i64] : ptr
|
func mem.realloc?[x: ptr, new_size: i64] : ptr
|
||||||
@@ -198,7 +198,7 @@ func mem.realloc?[x: ptr, new_size: i64] : ptr
|
|||||||
let b: mem.Block = next->next
|
let b: mem.Block = next->next
|
||||||
b->prev = blk
|
b->prev = blk
|
||||||
if mem.read64(_builtin_heap_tail()) == next as ptr
|
if mem.read64(_builtin_heap_tail()) == next as ptr
|
||||||
mem.write64(_builtin_heap_tail(), blk as ptr as i64)
|
mem.write64(_builtin_heap_tail(), blk)
|
||||||
mem._split_block(blk, new_size)
|
mem._split_block(blk, new_size)
|
||||||
return x
|
return x
|
||||||
|
|
||||||
@@ -260,7 +260,7 @@ func mem.write16be[x: ptr, d: i64] : void
|
|||||||
x[0] = (d >> 8) & 0xff
|
x[0] = (d >> 8) & 0xff
|
||||||
x[1] = d & 0xff
|
x[1] = d & 0xff
|
||||||
|
|
||||||
func mem.write64[x: ptr, d: i64] : void
|
func mem.write64[x: ptr, d: any] : void
|
||||||
_builtin_set64(x, d)
|
_builtin_set64(x, d)
|
||||||
|
|
||||||
// see emit_prologue for the io.printf wrapper
|
// see emit_prologue for the io.printf wrapper
|
||||||
@@ -330,12 +330,12 @@ func io.read_char[] : u8
|
|||||||
|
|
||||||
func io.read_line[]: str
|
func io.read_line[]: str
|
||||||
let MAX_SIZE = 60000
|
let MAX_SIZE = 60000
|
||||||
let buffer: str = mem.alloc(MAX_SIZE + 1) as str
|
let buffer: str = mem.alloc(MAX_SIZE + 1)
|
||||||
let n: i64 = _builtin_syscall(SYS_read, 0, buffer, MAX_SIZE)
|
let n: i64 = _builtin_syscall(SYS_read, 0, buffer, MAX_SIZE)
|
||||||
if n < 0
|
if n < 0
|
||||||
n = 0
|
n = 0
|
||||||
buffer[n] = 0
|
buffer[n] = 0
|
||||||
buffer = must(mem.realloc?(buffer, n + 1) as str)
|
buffer = must(mem.realloc?(buffer, n + 1))
|
||||||
return buffer
|
return buffer
|
||||||
|
|
||||||
struct io.Buffer
|
struct io.Buffer
|
||||||
@@ -436,7 +436,7 @@ func str.len[s: str] : i64
|
|||||||
|
|
||||||
func str.make_copy[s: str] : str
|
func str.make_copy[s: str] : str
|
||||||
let size: i64 = str.len(s) + 1
|
let size: i64 = str.len(s) + 1
|
||||||
let dup: str = mem.alloc(size) as str
|
let dup: str = mem.alloc(size)
|
||||||
mem.copy(s as ptr, dup as ptr, size)
|
mem.copy(s as ptr, dup as ptr, size)
|
||||||
return dup
|
return dup
|
||||||
|
|
||||||
@@ -472,7 +472,7 @@ func str.is_alphanumeric[x: u8] : bool
|
|||||||
func str.concat[a: str, b: str] : str
|
func str.concat[a: str, b: str] : str
|
||||||
let a_len: i64 = str.len(a)
|
let a_len: i64 = str.len(a)
|
||||||
let b_len: i64 = str.len(b)
|
let b_len: i64 = str.len(b)
|
||||||
let out: str = mem.alloc(a_len + b_len + 1) as str
|
let out: str = mem.alloc(a_len + b_len + 1)
|
||||||
mem.copy(a as ptr, out as ptr, a_len)
|
mem.copy(a as ptr, out as ptr, a_len)
|
||||||
mem.copy(b as ptr, out as ptr + a_len, b_len)
|
mem.copy(b as ptr, out as ptr + a_len, b_len)
|
||||||
out[a_len + b_len] = 0
|
out[a_len + b_len] = 0
|
||||||
@@ -505,7 +505,7 @@ func str.substr[s: str, start: i64, length: i64] : str
|
|||||||
if start < 0 || length < 0 || start + length > str.len(s)
|
if start < 0 || length < 0 || start + length > str.len(s)
|
||||||
panic("str.substr out of bounds")
|
panic("str.substr out of bounds")
|
||||||
|
|
||||||
let out: str = mem.alloc(length + 1) as str
|
let out: str = mem.alloc(length + 1)
|
||||||
mem.copy(s as ptr + start, out as ptr, length)
|
mem.copy(s as ptr + start, out as ptr, length)
|
||||||
out[length] = 0
|
out[length] = 0
|
||||||
return out
|
return out
|
||||||
@@ -513,7 +513,7 @@ func str.substr[s: str, start: i64, length: i64] : str
|
|||||||
func str.trim[s: str] : str
|
func str.trim[s: str] : str
|
||||||
let len: i64 = str.len(s)
|
let len: i64 = str.len(s)
|
||||||
if len == 0
|
if len == 0
|
||||||
let out: str = mem.alloc(1) as str
|
let out: str = mem.alloc(1)
|
||||||
out[0] = 0
|
out[0] = 0
|
||||||
return out
|
return out
|
||||||
|
|
||||||
@@ -562,7 +562,7 @@ func str.split[haystack: str, needle: str]: Array
|
|||||||
|
|
||||||
func str.reverse[s: str] : str
|
func str.reverse[s: str] : str
|
||||||
let len: i64 = str.len(s)
|
let len: i64 = str.len(s)
|
||||||
let out: str = mem.alloc(len + 1) as str
|
let out: str = mem.alloc(len + 1)
|
||||||
|
|
||||||
for i in 0..len
|
for i in 0..len
|
||||||
out[i] = s[len - i - 1]
|
out[i] = s[len - i - 1]
|
||||||
@@ -571,7 +571,7 @@ func str.reverse[s: str] : str
|
|||||||
|
|
||||||
func str.from_i64[n: i64] : str
|
func str.from_i64[n: i64] : str
|
||||||
if n == 0
|
if n == 0
|
||||||
let out: str = mem.alloc(2) as str
|
let out: str = mem.alloc(2)
|
||||||
out[0] = '0'
|
out[0] = '0'
|
||||||
out[1] = 0
|
out[1] = 0
|
||||||
return out
|
return out
|
||||||
@@ -582,7 +582,7 @@ func str.from_i64[n: i64] : str
|
|||||||
if n == -9223372036854775808
|
if n == -9223372036854775808
|
||||||
return str.make_copy("-9223372036854775808")
|
return str.make_copy("-9223372036854775808")
|
||||||
n = -n
|
n = -n
|
||||||
let buf: str = mem.alloc(21) as str // enough to fit -MAX_I64
|
let buf: str = mem.alloc(21) // enough to fit -MAX_I64
|
||||||
let end = 20
|
let end = 20
|
||||||
buf[end] = 0
|
buf[end] = 0
|
||||||
end = end - 1
|
end = end - 1
|
||||||
@@ -601,13 +601,13 @@ func str.hex_from_i64[n: i64] : str
|
|||||||
let hex_chars: str = "0123456789abcdef"
|
let hex_chars: str = "0123456789abcdef"
|
||||||
|
|
||||||
if n == 0
|
if n == 0
|
||||||
let out: str = mem.alloc(2) as str
|
let out: str = mem.alloc(2)
|
||||||
out[0] = '0'
|
out[0] = '0'
|
||||||
out[1] = 0
|
out[1] = 0
|
||||||
return out
|
return out
|
||||||
|
|
||||||
let mask: i64 = (1 << 60) - 1
|
let mask: i64 = (1 << 60) - 1
|
||||||
let buf: str = mem.alloc(17) as str
|
let buf: str = mem.alloc(17)
|
||||||
let len = 0
|
let len = 0
|
||||||
|
|
||||||
while n != 0
|
while n != 0
|
||||||
@@ -615,7 +615,7 @@ func str.hex_from_i64[n: i64] : str
|
|||||||
n = (n >> 4) & mask
|
n = (n >> 4) & mask
|
||||||
len = len + 1
|
len = len + 1
|
||||||
|
|
||||||
let out: str = mem.alloc(len + 1) as str
|
let out: str = mem.alloc(len + 1)
|
||||||
let j = 0
|
let j = 0
|
||||||
while j < len
|
while j < len
|
||||||
out[j] = buf[len - 1 - j]
|
out[j] = buf[len - 1 - j]
|
||||||
@@ -626,7 +626,7 @@ func str.hex_from_i64[n: i64] : str
|
|||||||
return out
|
return out
|
||||||
|
|
||||||
func str.from_char[c: u8] : str
|
func str.from_char[c: u8] : str
|
||||||
let s: str = mem.alloc(2) as str
|
let s: str = mem.alloc(2)
|
||||||
s[0] = c
|
s[0] = c
|
||||||
s[1] = 0
|
s[1] = 0
|
||||||
return s
|
return s
|
||||||
@@ -652,7 +652,7 @@ func str.parse_i64[s: str] : i64
|
|||||||
func str.hex_encode[s: str, s_len: i64] : str
|
func str.hex_encode[s: str, s_len: i64] : str
|
||||||
let hex_chars: str = "0123456789abcdef"
|
let hex_chars: str = "0123456789abcdef"
|
||||||
let j = 0
|
let j = 0
|
||||||
let out: str = mem.alloc(s_len * 2 + 1) as str
|
let out: str = mem.alloc(s_len * 2 + 1)
|
||||||
|
|
||||||
for i in 0..s_len
|
for i in 0..s_len
|
||||||
let high: u8 = (s[i] >> 4) & 15
|
let high: u8 = (s[i] >> 4) & 15
|
||||||
@@ -678,7 +678,7 @@ func str.hex_decode[s: str] : str
|
|||||||
|
|
||||||
let i = 0
|
let i = 0
|
||||||
let j = 0
|
let j = 0
|
||||||
let out: str = mem.alloc(s_len / 2 + 1) as str
|
let out: str = mem.alloc(s_len / 2 + 1)
|
||||||
|
|
||||||
while i < s_len
|
while i < s_len
|
||||||
out[j] = str._hex_digit_to_int(s[i]) * 16 + str._hex_digit_to_int(s[i + 1])
|
out[j] = str._hex_digit_to_int(s[i]) * 16 + str._hex_digit_to_int(s[i + 1])
|
||||||
|
|||||||
@@ -4,13 +4,11 @@
|
|||||||
use std::{cell::RefCell, collections::HashMap, rc::Rc};
|
use std::{cell::RefCell, collections::HashMap, rc::Rc};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
analyzer::Analyzer,
|
analyzer::{Analyzer, Type},
|
||||||
parser::{Expr, Stmt},
|
parser::{Expr, Stmt},
|
||||||
tokenizer::{TokenType, ZernError, error},
|
tokenizer::{TokenType, ZernError, error},
|
||||||
};
|
};
|
||||||
|
|
||||||
type Type = String;
|
|
||||||
|
|
||||||
macro_rules! expect_type {
|
macro_rules! expect_type {
|
||||||
($expr_type:expr, $expected:expr, $loc:expr) => {
|
($expr_type:expr, $expected:expr, $loc:expr) => {
|
||||||
if $expected != "any" && $expr_type != "any" && $expr_type != $expected {
|
if $expected != "any" && $expr_type != "any" && $expr_type != $expected {
|
||||||
@@ -330,14 +328,15 @@ impl TypeChecker {
|
|||||||
.functions
|
.functions
|
||||||
.contains_key(&callee_name.lexeme)
|
.contains_key(&callee_name.lexeme)
|
||||||
{
|
{
|
||||||
let params = self.analyzer.borrow().functions[&callee_name.lexeme].clone();
|
let fn_type =
|
||||||
if let (_, Some(params)) = params {
|
&self.analyzer.borrow().functions[&callee_name.lexeme].clone();
|
||||||
|
if let Some(params) = fn_type.params.clone() {
|
||||||
// its a function (defined/builtin/extern)
|
// its a function (defined/builtin/extern)
|
||||||
for (i, arg) in args.iter().enumerate() {
|
for (i, arg) in args.iter().enumerate() {
|
||||||
expect_type!(self.typecheck_expr(env, arg)?, params[i], paren.loc);
|
expect_type!(self.typecheck_expr(env, arg)?, params[i], paren.loc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(params.0)
|
Ok(fn_type.return_type.clone())
|
||||||
} else {
|
} else {
|
||||||
// its a variable containing function address
|
// its a variable containing function address
|
||||||
expect_type!(self.typecheck_expr(env, callee)?, "fnptr", paren.loc);
|
expect_type!(self.typecheck_expr(env, callee)?, "fnptr", paren.loc);
|
||||||
|
|||||||
Reference in New Issue
Block a user