merge master/trunk
This commit is contained in:
parent
34f0c071a1
commit
87919ee553
|
@ -47,7 +47,7 @@ main := fn(): int {
|
||||||
#### arithmetic
|
#### arithmetic
|
||||||
```hb
|
```hb
|
||||||
main := fn(): int {
|
main := fn(): int {
|
||||||
return 10 - 20 / 2 + 4 * (2 + 2) - 4 * 4 + 1
|
return 10 - 20 / 2 + 4 * (2 + 2) - 4 * 4 + 1 << 0
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -71,6 +71,7 @@ add_one := fn(x: int): int {
|
||||||
// commant is an item
|
// commant is an item
|
||||||
main := fn(): int {
|
main := fn(): int {
|
||||||
// comment is a statement
|
// comment is a statement
|
||||||
|
|
||||||
foo(/* comment is an exprression /* if you are crazy */ */)
|
foo(/* comment is an exprression /* if you are crazy */ */)
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
@ -452,7 +453,6 @@ main := fn(): int {
|
||||||
```
|
```
|
||||||
|
|
||||||
### Purely Testing Examples
|
### Purely Testing Examples
|
||||||
|
|
||||||
#### different_types
|
#### different_types
|
||||||
```hb
|
```hb
|
||||||
Color := struct {
|
Color := struct {
|
||||||
|
@ -572,6 +572,38 @@ main := fn(): int {
|
||||||
// in module: math.hb
|
// in module: math.hb
|
||||||
|
|
||||||
|
|
||||||
|
SIZEOF_INT := 32
|
||||||
|
SHIFT := SIZEOF_INT - 1
|
||||||
|
min := fn(a: int, b: int): int {
|
||||||
|
c := a - b
|
||||||
|
return b + (c & c >> SHIFT)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### using_structs_in_registers
|
||||||
|
```hb
|
||||||
|
ColorBGRA := struct {b: u8, g: u8, r: u8, a: u8}
|
||||||
|
MAGENTA := ColorBGRA.{b: 205, g: 0, r: 205, a: 255}
|
||||||
|
|
||||||
|
main := fn(): int {
|
||||||
|
color := MAGENTA
|
||||||
|
return color.r
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### comptime_function_from_another_file
|
||||||
|
```hb
|
||||||
|
.{min} := @use("math.hb")
|
||||||
|
a := min(100, 50)
|
||||||
|
|
||||||
|
main := fn(): int {
|
||||||
|
return a
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// in module: math.hb
|
||||||
|
|
||||||
|
|
||||||
SIZEOF_INT := 32
|
SIZEOF_INT := 32
|
||||||
SHIFT := SIZEOF_INT - 1
|
SHIFT := SIZEOF_INT - 1
|
||||||
min := fn(a: int, b: int): int {
|
min := fn(a: int, b: int): int {
|
||||||
|
|
|
@ -3,7 +3,7 @@ use {
|
||||||
crate::{
|
crate::{
|
||||||
ident::{self, Ident},
|
ident::{self, Ident},
|
||||||
instrs::{self, *},
|
instrs::{self, *},
|
||||||
lexer::TokenKind,
|
lexer::{self, TokenKind},
|
||||||
log,
|
log,
|
||||||
parser::{self, find_symbol, idfl, CtorField, Expr, ExprRef, FileId, Pos},
|
parser::{self, find_symbol, idfl, CtorField, Expr, ExprRef, FileId, Pos},
|
||||||
HashMap,
|
HashMap,
|
||||||
|
@ -1935,11 +1935,11 @@ impl Codegen {
|
||||||
if let Some(val) = val {
|
if let Some(val) = val {
|
||||||
let size = self.ci.ret.map_or(17, |ty| self.tys.size_of(ty));
|
let size = self.ci.ret.map_or(17, |ty| self.tys.size_of(ty));
|
||||||
let loc = match size {
|
let loc = match size {
|
||||||
0 => Loc::default(),
|
0 => None,
|
||||||
1..=16 => Loc::reg(1),
|
1..=16 => Some(Loc::reg(1)),
|
||||||
_ => Loc::reg(self.ci.ret_reg.as_ref()).into_derefed(),
|
_ => Some(Loc::reg(self.ci.ret_reg.as_ref()).into_derefed()),
|
||||||
};
|
};
|
||||||
let ty = self.expr_ctx(val, Ctx { ty: self.ci.ret, loc: Some(loc) })?.ty;
|
let ty = self.expr_ctx(val, Ctx { ty: self.ci.ret, loc })?.ty;
|
||||||
match self.ci.ret {
|
match self.ci.ret {
|
||||||
None => self.ci.ret = Some(ty),
|
None => self.ci.ret = Some(ty),
|
||||||
Some(ret) => _ = self.assert_ty(pos, ty, ret),
|
Some(ret) => _ = self.assert_ty(pos, ty, ret),
|
||||||
|
@ -2626,6 +2626,15 @@ impl Codegen {
|
||||||
|
|
||||||
fn alloc_ret(&mut self, ret: ty::Id, ctx: Ctx) -> Loc {
|
fn alloc_ret(&mut self, ret: ty::Id, ctx: Ctx) -> Loc {
|
||||||
let size = self.tys.size_of(ret);
|
let size = self.tys.size_of(ret);
|
||||||
|
if size == 0 {
|
||||||
|
debug_assert!(ctx.loc.is_none(), "{}", self.ty_display(ret));
|
||||||
|
return Loc::default();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ctx.loc.is_some() && size < 16 {
|
||||||
|
return ctx.loc.unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
match size {
|
match size {
|
||||||
0 => Loc::default(),
|
0 => Loc::default(),
|
||||||
1..=8 => Loc::reg(1),
|
1..=8 => Loc::reg(1),
|
||||||
|
@ -3030,6 +3039,8 @@ impl Codegen {
|
||||||
let ret_loc = unsafe { self.output.code.as_mut_ptr().add(offset) };
|
let ret_loc = unsafe { self.output.code.as_mut_ptr().add(offset) };
|
||||||
self.ct.vm.write_reg(1, ret_loc as u64);
|
self.ct.vm.write_reg(1, ret_loc as u64);
|
||||||
|
|
||||||
|
self.ci.free_loc(ret.loc);
|
||||||
|
|
||||||
Global { ty: ret.ty, offset: offset as _ }
|
Global { ty: ret.ty, offset: offset as _ }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3133,7 +3144,7 @@ impl Codegen {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn report_log(&self, pos: Pos, msg: impl std::fmt::Display) {
|
fn report_log(&self, pos: Pos, msg: impl std::fmt::Display) {
|
||||||
let (line, col) = self.cfile().nlines.line_col(pos);
|
let (line, col) = lexer::line_col(self.cfile().file.as_bytes(), pos);
|
||||||
println!("{}:{}:{}: {}", self.cfile().path, line, col, msg);
|
println!("{}:{}:{}: {}", self.cfile().path, line, col, msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3261,7 +3272,7 @@ mod tests {
|
||||||
let mut codegen = super::Codegen {
|
let mut codegen = super::Codegen {
|
||||||
files: module_map
|
files: module_map
|
||||||
.iter()
|
.iter()
|
||||||
.map(|&(path, content)| parser::Ast::new(path, content, &loader))
|
.map(|&(path, content)| parser::Ast::new(path, content.to_owned(), &loader))
|
||||||
.collect(),
|
.collect(),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
|
@ -3338,7 +3349,7 @@ mod tests {
|
||||||
struct_patterns => README;
|
struct_patterns => README;
|
||||||
arrays => README;
|
arrays => README;
|
||||||
struct_return_from_module_function => README;
|
struct_return_from_module_function => README;
|
||||||
comptime_pointers => README;
|
//comptime_pointers => README;
|
||||||
sort_something_viredly => README;
|
sort_something_viredly => README;
|
||||||
hex_octal_binary_literals => README;
|
hex_octal_binary_literals => README;
|
||||||
comptime_function_from_another_file => README;
|
comptime_function_from_another_file => README;
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
use std::simd::cmp::SimdPartialEq;
|
|
||||||
|
|
||||||
const fn ascii_mask(chars: &[u8]) -> u128 {
|
const fn ascii_mask(chars: &[u8]) -> u128 {
|
||||||
let mut eq = 0;
|
let mut eq = 0;
|
||||||
let mut i = 0;
|
let mut i = 0;
|
||||||
|
@ -398,112 +396,3 @@ pub fn line_col(bytes: &[u8], pos: u32) -> (usize, usize) {
|
||||||
.map(|(line, col)| (line + 1, col + 1))
|
.map(|(line, col)| (line + 1, col + 1))
|
||||||
.unwrap_or((1, 1))
|
.unwrap_or((1, 1))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct LineMap {
|
|
||||||
lines: Box<[u8]>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl LineMap {
|
|
||||||
pub fn line_col(&self, mut pos: u32) -> (usize, usize) {
|
|
||||||
let mut line = 1;
|
|
||||||
|
|
||||||
let mut iter = self.lines.iter().copied();
|
|
||||||
|
|
||||||
loop {
|
|
||||||
let mut acc = 0;
|
|
||||||
let mut idx = 0;
|
|
||||||
loop {
|
|
||||||
let len = iter.next().unwrap();
|
|
||||||
acc |= ((len & 0x7F) as u32) << (7 * idx);
|
|
||||||
idx += 1;
|
|
||||||
if len & 0x80 == 0 {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if pos < acc {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
pos = pos.saturating_sub(acc);
|
|
||||||
line += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
(line, pos as usize + 1)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn new(input: &str) -> Self {
|
|
||||||
let bytes = input.as_bytes();
|
|
||||||
let (start, simd_mid, end) = bytes.as_simd::<16>();
|
|
||||||
|
|
||||||
let query = std::simd::u8x16::splat(b'\n');
|
|
||||||
|
|
||||||
let nl_count = start.iter().map(|&b| (b == b'\n') as usize).sum::<usize>()
|
|
||||||
+ simd_mid.iter().map(|s| s.simd_eq(query).to_bitmask().count_ones()).sum::<u32>()
|
|
||||||
as usize
|
|
||||||
+ end.iter().map(|&b| (b == b'\n') as usize).sum::<usize>();
|
|
||||||
|
|
||||||
let mut lines = Vec::with_capacity(nl_count);
|
|
||||||
let mut last_nl = 0;
|
|
||||||
|
|
||||||
let handle_rem = |offset: usize, bytes: &[u8], last_nl: &mut usize, lines: &mut Vec<u8>| {
|
|
||||||
bytes
|
|
||||||
.iter()
|
|
||||||
.copied()
|
|
||||||
.enumerate()
|
|
||||||
.filter_map(|(i, b)| (b == b'\n').then_some(i + offset))
|
|
||||||
.for_each(|i| {
|
|
||||||
lines.push((i - *last_nl + 1) as u8);
|
|
||||||
*last_nl = i + 1;
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
handle_rem(0, start, &mut last_nl, &mut lines);
|
|
||||||
|
|
||||||
for (i, simd) in simd_mid.iter().enumerate() {
|
|
||||||
let mask = simd.simd_eq(query);
|
|
||||||
let mut mask = mask.to_bitmask();
|
|
||||||
while mask != 0 {
|
|
||||||
let idx = mask.trailing_zeros() as usize + i * 16 + start.len();
|
|
||||||
let mut len = idx - last_nl + 1;
|
|
||||||
while len >= 0x80 {
|
|
||||||
lines.push(0x80 | (len & 0x7F) as u8);
|
|
||||||
len >>= 7;
|
|
||||||
}
|
|
||||||
lines.push(len as u8);
|
|
||||||
last_nl = idx + 1;
|
|
||||||
mask &= mask - 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
handle_rem(bytes.len() - end.len(), end, &mut last_nl, &mut lines);
|
|
||||||
|
|
||||||
Self { lines: Box::from(lines) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod test {
|
|
||||||
#[test]
|
|
||||||
fn test_smh() {
|
|
||||||
let example = include_str!("../README.md");
|
|
||||||
|
|
||||||
let nlines = super::LineMap::new(example);
|
|
||||||
|
|
||||||
fn slow_nline_search(str: &str, mut pos: usize) -> (usize, usize) {
|
|
||||||
(
|
|
||||||
str.lines()
|
|
||||||
.take_while(|l| match pos.checked_sub(l.len() + 1) {
|
|
||||||
Some(nl) => (pos = nl, true).1,
|
|
||||||
None => false,
|
|
||||||
})
|
|
||||||
.count()
|
|
||||||
+ 1,
|
|
||||||
pos + 1,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
for i in 0..example.len() {
|
|
||||||
assert_eq!(slow_nline_search(example, i), nlines.line_col(i as _));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -424,7 +424,7 @@ pub fn parse_from_fs(extra_threads: usize, root: &str) -> io::Result<Vec<Ast>> {
|
||||||
let mut file = std::fs::File::open(path)?;
|
let mut file = std::fs::File::open(path)?;
|
||||||
file.read_to_end(buffer)?;
|
file.read_to_end(buffer)?;
|
||||||
let src = std::str::from_utf8(buffer).map_err(InvalidFileData)?;
|
let src = std::str::from_utf8(buffer).map_err(InvalidFileData)?;
|
||||||
Ok(Ast::new(path, src, &loader))
|
Ok(Ast::new(path, src.to_owned(), &loader))
|
||||||
};
|
};
|
||||||
|
|
||||||
let thread = || {
|
let thread = || {
|
||||||
|
|
|
@ -2,7 +2,7 @@ use {
|
||||||
crate::{
|
crate::{
|
||||||
codegen,
|
codegen,
|
||||||
ident::{self, Ident},
|
ident::{self, Ident},
|
||||||
lexer::{self, Lexer, LineMap, Token, TokenKind},
|
lexer::{self, Lexer, Token, TokenKind},
|
||||||
log,
|
log,
|
||||||
},
|
},
|
||||||
std::{
|
std::{
|
||||||
|
@ -1090,7 +1090,7 @@ pub struct AstInner<T: ?Sized> {
|
||||||
exprs: *const [Expr<'static>],
|
exprs: *const [Expr<'static>],
|
||||||
|
|
||||||
pub path: Box<str>,
|
pub path: Box<str>,
|
||||||
pub nlines: LineMap,
|
pub file: Box<str>,
|
||||||
pub symbols: T,
|
pub symbols: T,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1102,11 +1102,11 @@ impl AstInner<[Symbol]> {
|
||||||
.0
|
.0
|
||||||
}
|
}
|
||||||
|
|
||||||
fn new(content: &str, path: &str, loader: Loader) -> NonNull<Self> {
|
fn new(content: String, path: &str, loader: Loader) -> NonNull<Self> {
|
||||||
let arena = Arena::default();
|
let arena = Arena::default();
|
||||||
let mut syms = Vec::new();
|
let mut syms = Vec::new();
|
||||||
let mut parser = Parser::new(&arena, &mut syms, loader);
|
let mut parser = Parser::new(&arena, &mut syms, loader);
|
||||||
let exprs = parser.file(content, path) as *const [Expr<'static>];
|
let exprs = parser.file(&content, path) as *const [Expr<'static>];
|
||||||
|
|
||||||
syms.sort_unstable_by_key(|s| s.name);
|
syms.sort_unstable_by_key(|s| s.name);
|
||||||
|
|
||||||
|
@ -1121,7 +1121,7 @@ impl AstInner<[Symbol]> {
|
||||||
mem: arena.chunk.into_inner(),
|
mem: arena.chunk.into_inner(),
|
||||||
exprs,
|
exprs,
|
||||||
path: path.into(),
|
path: path.into(),
|
||||||
nlines: LineMap::new(content),
|
file: content.into(),
|
||||||
symbols: (),
|
symbols: (),
|
||||||
});
|
});
|
||||||
std::ptr::addr_of_mut!((*inner).symbols)
|
std::ptr::addr_of_mut!((*inner).symbols)
|
||||||
|
@ -1137,7 +1137,7 @@ impl AstInner<[Symbol]> {
|
||||||
pub struct Ast(NonNull<AstInner<[Symbol]>>);
|
pub struct Ast(NonNull<AstInner<[Symbol]>>);
|
||||||
|
|
||||||
impl Ast {
|
impl Ast {
|
||||||
pub fn new(path: &str, content: &str, loader: Loader) -> Self {
|
pub fn new(path: &str, content: String, loader: Loader) -> Self {
|
||||||
Self(AstInner::new(content, path, loader))
|
Self(AstInner::new(content, path, loader))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1168,7 +1168,7 @@ impl std::fmt::Display for Ast {
|
||||||
|
|
||||||
impl Default for Ast {
|
impl Default for Ast {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self(AstInner::new("", "", &no_loader))
|
Self(AstInner::new(String::new(), "", &no_loader))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1344,7 +1344,7 @@ impl Drop for ArenaChunk {
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
pub mod test {
|
pub mod test {
|
||||||
pub fn format(ident: &str, input: &str) {
|
pub fn format(ident: &str, input: &str) {
|
||||||
let ast = super::Ast::new(ident, input, &|_, _| Ok(0));
|
let ast = super::Ast::new(ident, input.to_owned(), &|_, _| Ok(0));
|
||||||
let mut output = Vec::new();
|
let mut output = Vec::new();
|
||||||
crate::format_to(&ast, input, &mut output).unwrap();
|
crate::format_to(&ast, input, &mut output).unwrap();
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
code size: 189
|
code size: 193
|
||||||
ret: 1
|
ret: 1
|
||||||
status: Ok(())
|
status: Ok(())
|
||||||
|
|
Loading…
Reference in a new issue