improved exer

This commit is contained in:
mlokr 2024-06-25 18:39:59 +02:00
parent 33eea02670
commit f9fa7f82e9
4 changed files with 129 additions and 91 deletions

View file

@ -84,10 +84,10 @@ fib := fn(x: int): int {
#### variables #### variables
```hb ```hb
main := fn(): int { main := fn(): int {
a := 1; := 1;
b := 2; b := 2;
a = a + 1; ඞ = ඞ + 1;
return a - b; return - b;
} }
``` ```
@ -275,7 +275,7 @@ push := fn($Elem: type, vec: ^Vec(Elem), value: Elem): ^Elem {
} }
new_alloc := @as(^Elem, @bitcast(malloc(vec.cap * @sizeof(Elem), @alignof(Elem)))); new_alloc := @as(^Elem, @bitcast(malloc(vec.cap * @sizeof(Elem), @alignof(Elem))));
if @as(uint, @bitcast(new_alloc)) == 0 return @bitcast(0); if new_alloc == 0 return 0;
src_cursor := vec.data; src_cursor := vec.data;
dst_cursor := new_alloc; dst_cursor := new_alloc;

View file

@ -1,4 +1,4 @@
use std::{ops::Range, rc::Rc, usize}; use std::{ops::Range, rc::Rc};
use crate::{ use crate::{
ident::{self, Ident}, ident::{self, Ident},

View file

@ -1,5 +1,16 @@
use std::simd::cmp::SimdPartialEq; use std::simd::cmp::SimdPartialEq;
const fn ascii_mask(chars: &[u8]) -> u128 {
let mut eq = 0;
let mut i = 0;
while i < chars.len() {
let b = chars[i];
eq |= 1 << b;
i += 1;
}
eq
}
#[derive(Debug, PartialEq, Eq, Clone, Copy)] #[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub struct Token { pub struct Token {
pub kind: TokenKind, pub kind: TokenKind,
@ -35,15 +46,15 @@ macro_rules! gen_token_kind {
) => { ) => {
impl std::fmt::Display for $name { impl std::fmt::Display for $name {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
let s = match *self { let sf = *self as u8;
f.write_str(match *self {
$( Self::$pattern => concat!('<', stringify!($pattern), '>'), )* $( Self::$pattern => concat!('<', stringify!($pattern), '>'), )*
$( Self::$keyword => stringify!($keyword_lit), )* $( Self::$keyword => stringify!($keyword_lit), )*
$( Self::$punkt => stringify!($punkt_lit), )* $( Self::$punkt => stringify!($punkt_lit), )*
$($( Self::$op => $op_lit, $($( Self::$op => $op_lit,
$(Self::$assign => concat!($op_lit, "="),)?)*)* $(Self::$assign => concat!($op_lit, "="),)?)*)*
}; _ => unsafe { std::str::from_utf8_unchecked(std::slice::from_ref(&sf)) },
f.write_str(s) })
} }
} }
@ -64,23 +75,98 @@ macro_rules! gen_token_kind {
_ => Self::Ident, _ => Self::Ident,
} }
} }
pub fn assign_op(&self) -> Option<Self> {
Some(match self {
$($($(Self::$assign => Self::$op,)?)*)*
_ => return None,
})
} }
};
} }
#[derive(Debug, PartialEq, Eq, Clone, Copy)] #[derive(Debug, PartialEq, Eq, Clone, Copy)]
$vis enum $name { #[repr(u8)]
$( $pattern, )* pub enum TokenKind {
$( $keyword, )* Not = b'!',
$( $punkt, )* DQuote = b'"',
$($( $op, $($assign,)? )*)* Pound = b'#',
CtIdent = b'$',
Mod = b'%',
Band = b'&',
Quote = b'\'',
LParen = b'(',
RParen = b')',
Mul = b'*',
Add = b'+',
Comma = b',',
Sub = b'-',
Dot = b'.',
Div = b'/',
Shl = b'0',
Shr = b'1',
// Unused = 2-9
Colon = b':',
Semi = b';',
Gt = b'>',
Assign = b'=',
Lt = b'<',
Que = b'?',
Directive = b'@',
Ident,
Number,
Eof,
String,
Return,
If,
Else,
Loop,
Break,
Continue,
Fn,
Struct,
True,
Ctor,
Tupl,
Or,
And,
// Unused = R-Z
LBrack = b'[',
BSlash = b'\\',
RBrack = b']',
Xor = b'^',
Tick = b'`',
// Unused = a-z
LBrace = b'{',
Bor = b'|',
RBrace = b'}',
Tilde = b'~',
Decl = b':' + 128,
Eq = b'=' + 128,
Ne = b'!' + 128,
Le = b'<' + 128,
Ge = b'>' + 128,
BorAss = b'|' + 128,
AddAss = b'+' + 128,
SubAss = b'-' + 128,
MulAss = b'*' + 128,
DivAss = b'/' + 128,
ModAss = b'%' + 128,
XorAss = b'^' + 128,
BandAss = b'&' + 128,
ShlAss = b'0' + 128,
ShrAss = b'1' + 128,
}
impl TokenKind {
pub fn assign_op(self) -> Option<Self> {
let id = (self as u8).saturating_sub(128);
if ascii_mask(b"|+-*/%^&01") & (1u128 << id) == 0 {
return None;
}
Some(unsafe { std::mem::transmute::<u8, Self>(id) })
} }
};
} }
gen_token_kind! { gen_token_kind! {
@ -90,8 +176,7 @@ gen_token_kind! {
Ident, Ident,
Number, Number,
Eof, Eof,
Error, Directive,
Driective,
String, String,
#[keywords] #[keywords]
Return = b"return", Return = b"return",
@ -104,14 +189,6 @@ gen_token_kind! {
Struct = b"struct", Struct = b"struct",
True = b"true", True = b"true",
#[punkt] #[punkt]
LParen = "(",
RParen = ")",
LBrace = "{",
RBrace = "}",
Semi = ";",
Colon = ":",
Comma = ",",
Dot = ".",
Ctor = ".{", Ctor = ".{",
Tupl = ".(", Tupl = ".(",
#[ops] #[ops]
@ -194,30 +271,20 @@ impl<'a> Lexer<'a> {
}; };
let advance_ident = |s: &mut Self| { let advance_ident = |s: &mut Self| {
while let Some(b'a'..=b'z' | b'A'..=b'Z' | b'0'..=b'9' | b'_') = s.peek() { while let Some(b'a'..=b'z' | b'A'..=b'Z' | b'0'..=b'9' | b'_' | 127..) = s.peek() {
s.advance(); s.advance();
} }
}; };
let kind = match c { let mut kind = match c {
b'\n' | b'\r' | b'\t' | b' ' => continue, ..=b' ' => continue,
b'0'..=b'9' => { b'0'..=b'9' => {
while let Some(b'0'..=b'9') = self.peek() { while let Some(b'0'..=b'9') = self.peek() {
self.advance(); self.advance();
} }
T::Number T::Number
} }
b'@' => { b'a'..=b'z' | b'A'..=b'Z' | b'_' | 127.. => {
start += 1;
advance_ident(self);
T::Driective
}
b'$' => {
start += 1;
advance_ident(self);
T::CtIdent
}
b'a'..=b'z' | b'A'..=b'Z' | b'_' => {
advance_ident(self); advance_ident(self);
let ident = &self.bytes[start as usize..self.pos as usize]; let ident = &self.bytes[start as usize..self.pos as usize];
T::from_ident(ident) T::from_ident(ident)
@ -232,53 +299,24 @@ impl<'a> Lexer<'a> {
} }
T::String T::String
} }
b':' if self.advance_if(b'=') => T::Decl,
b':' => T::Colon,
b',' => T::Comma,
b'.' if self.advance_if(b'{') => T::Ctor, b'.' if self.advance_if(b'{') => T::Ctor,
b'.' if self.advance_if(b'(') => T::Tupl, b'.' if self.advance_if(b'(') => T::Tupl,
b'.' => T::Dot, b'<' if self.advance_if(b'<') => T::Shl,
b';' => T::Semi, b'>' if self.advance_if(b'>') => T::Shr,
b'!' if self.advance_if(b'=') => T::Ne,
b'=' if self.advance_if(b'=') => T::Eq,
b'=' => T::Assign,
b'<' if self.advance_if(b'=') => T::Le,
b'<' if self.advance_if(b'<') => match self.advance_if(b'=') {
true => T::ShlAss,
false => T::Shl,
},
b'<' => T::Lt,
b'>' if self.advance_if(b'=') => T::Ge,
b'>' if self.advance_if(b'>') => match self.advance_if(b'=') {
true => T::ShrAss,
false => T::Shr,
},
b'>' => T::Gt,
b'+' if self.advance_if(b'=') => T::AddAss,
b'+' => T::Add,
b'-' if self.advance_if(b'=') => T::SubAss,
b'-' => T::Sub,
b'*' if self.advance_if(b'=') => T::MulAss,
b'*' => T::Mul,
b'/' if self.advance_if(b'=') => T::DivAss,
b'/' => T::Div,
b'%' if self.advance_if(b'=') => T::ModAss,
b'%' => T::Mod,
b'&' if self.advance_if(b'=') => T::BandAss,
b'&' if self.advance_if(b'&') => T::And, b'&' if self.advance_if(b'&') => T::And,
b'&' => T::Band,
b'^' if self.advance_if(b'=') => T::XorAss,
b'^' => T::Xor,
b'|' if self.advance_if(b'=') => T::BorAss,
b'|' if self.advance_if(b'|') => T::Or, b'|' if self.advance_if(b'|') => T::Or,
b'|' => T::Bor, b => unsafe { std::mem::transmute::<u8, T>(b) },
b'(' => T::LParen,
b')' => T::RParen,
b'{' => T::LBrace,
b'}' => T::RBrace,
_ => T::Error,
}; };
if matches!(kind, T::Directive | T::CtIdent) {
start += 1;
advance_ident(self);
} else if ascii_mask(b":=!<>|+-*/%^&01") & (1u128 << kind as u8) != 0
&& self.advance_if(b'=')
{
kind = unsafe { std::mem::transmute::<u8, T>(kind as u8 + 128) };
}
return Token { return Token {
kind, kind,
start, start,

View file

@ -235,7 +235,7 @@ impl<'a, 'b> Parser<'a, 'b> {
let prev_boundary = self.ns_bound; let prev_boundary = self.ns_bound;
let prev_captured = self.captured.len(); let prev_captured = self.captured.len();
let mut expr = match token.kind { let mut expr = match token.kind {
T::Driective if self.lexer.slice(token.range()) == "use" => { T::Directive if self.lexer.slice(token.range()) == "use" => {
self.expect_advance(TokenKind::LParen); self.expect_advance(TokenKind::LParen);
let str = self.expect_advance(TokenKind::String); let str = self.expect_advance(TokenKind::String);
self.expect_advance(TokenKind::RParen); self.expect_advance(TokenKind::RParen);
@ -250,7 +250,7 @@ impl<'a, 'b> Parser<'a, 'b> {
}, },
} }
} }
T::Driective => E::Directive { T::Directive => E::Directive {
pos: token.start, pos: token.start,
name: self.move_str(token), name: self.move_str(token),
args: { args: {