forked from AbleOS/holey-bytes
improved exer
This commit is contained in:
parent
c85437e4e8
commit
6a69042cb7
|
@ -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;
|
||||||
|
|
|
@ -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},
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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: {
|
||||||
|
|
Loading…
Reference in a new issue