forked from AbleOS/holey-bytes
adding '<op>=' syntax
This commit is contained in:
parent
70955c1792
commit
3c09a5f23e
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
Type := struct {
|
Type := struct {
|
||||||
brah: int,
|
brah: int,
|
||||||
blah: int,
|
blah: int,
|
||||||
|
|
|
@ -12,7 +12,7 @@ fib := fn(n: int): int {
|
||||||
c := a + b;
|
c := a + b;
|
||||||
a = b;
|
a = b;
|
||||||
b = c;
|
b = c;
|
||||||
n = n - 1;
|
n -= 1;
|
||||||
|
|
||||||
stack_reclamation_edge_case := 0;
|
stack_reclamation_edge_case := 0;
|
||||||
|
|
||||||
|
|
|
@ -724,7 +724,7 @@ impl<'a> Codegen<'a> {
|
||||||
match *expr {
|
match *expr {
|
||||||
E::Ident { id, .. } if ident::is_null(id) => id,
|
E::Ident { id, .. } if ident::is_null(id) => id,
|
||||||
E::UnOp {
|
E::UnOp {
|
||||||
op: T::Star, val, ..
|
op: T::Mul, val, ..
|
||||||
} => {
|
} => {
|
||||||
let ty = self.ty(val);
|
let ty = self.ty(val);
|
||||||
self.alloc_pointer(ty)
|
self.alloc_pointer(ty)
|
||||||
|
@ -918,7 +918,7 @@ impl<'a> Codegen<'a> {
|
||||||
Some(Value { ty, loc })
|
Some(Value { ty, loc })
|
||||||
}
|
}
|
||||||
E::UnOp {
|
E::UnOp {
|
||||||
op: T::Amp,
|
op: T::Band,
|
||||||
val,
|
val,
|
||||||
pos,
|
pos,
|
||||||
} => {
|
} => {
|
||||||
|
@ -953,7 +953,7 @@ impl<'a> Codegen<'a> {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
E::UnOp {
|
E::UnOp {
|
||||||
op: T::Star,
|
op: T::Mul,
|
||||||
val,
|
val,
|
||||||
pos,
|
pos,
|
||||||
} => {
|
} => {
|
||||||
|
@ -1198,7 +1198,7 @@ impl<'a> Codegen<'a> {
|
||||||
self.display_ty(right.ty)
|
self.display_ty(right.ty)
|
||||||
);
|
);
|
||||||
|
|
||||||
if matches!(op, T::Plus | T::Minus) {
|
if matches!(op, T::Add | T::Sub) {
|
||||||
let min_size = lsize.min(rsize);
|
let min_size = lsize.min(rsize);
|
||||||
if bt::is_signed(ty) && min_size < size {
|
if bt::is_signed(ty) && min_size < size {
|
||||||
let operand = if lsize < rsize { lhs.0 } else { rhs.0 };
|
let operand = if lsize < rsize { lhs.0 } else { rhs.0 };
|
||||||
|
@ -1280,16 +1280,16 @@ impl<'a> Codegen<'a> {
|
||||||
use instrs as i;
|
use instrs as i;
|
||||||
Some(
|
Some(
|
||||||
match op {
|
match op {
|
||||||
T::Plus => [i::add8, i::add16, i::add32, i::add64],
|
T::Add => [i::add8, i::add16, i::add32, i::add64],
|
||||||
T::Minus => [i::sub8, i::sub16, i::sub32, i::sub64],
|
T::Sub => [i::sub8, i::sub16, i::sub32, i::sub64],
|
||||||
T::Star => [i::mul8, i::mul16, i::mul32, i::mul64],
|
T::Mul => [i::mul8, i::mul16, i::mul32, i::mul64],
|
||||||
T::FSlash if signed => [
|
T::Div if signed => [
|
||||||
|a, b, c| i::dirs8(a, ZERO, b, c),
|
|a, b, c| i::dirs8(a, ZERO, b, c),
|
||||||
|a, b, c| i::dirs16(a, ZERO, b, c),
|
|a, b, c| i::dirs16(a, ZERO, b, c),
|
||||||
|a, b, c| i::dirs32(a, ZERO, b, c),
|
|a, b, c| i::dirs32(a, ZERO, b, c),
|
||||||
|a, b, c| i::dirs64(a, ZERO, b, c),
|
|a, b, c| i::dirs64(a, ZERO, b, c),
|
||||||
],
|
],
|
||||||
T::FSlash => [
|
T::Div => [
|
||||||
|a, b, c| i::diru8(a, ZERO, b, c),
|
|a, b, c| i::diru8(a, ZERO, b, c),
|
||||||
|a, b, c| i::diru16(a, ZERO, b, c),
|
|a, b, c| i::diru16(a, ZERO, b, c),
|
||||||
|a, b, c| i::diru32(a, ZERO, b, c),
|
|a, b, c| i::diru32(a, ZERO, b, c),
|
||||||
|
|
|
@ -29,8 +29,8 @@ macro_rules! gen_token_kind {
|
||||||
$punkt:ident = $punkt_lit:literal,
|
$punkt:ident = $punkt_lit:literal,
|
||||||
)*
|
)*
|
||||||
#[ops] $(
|
#[ops] $(
|
||||||
#[prec = $prec:literal] $(
|
#[$prec:ident] $(
|
||||||
$op:ident = $op_lit:literal,
|
$op:ident = $op_lit:literal $(=> $assign:ident)?,
|
||||||
)*
|
)*
|
||||||
)*
|
)*
|
||||||
}
|
}
|
||||||
|
@ -42,7 +42,8 @@ macro_rules! gen_token_kind {
|
||||||
|
|
||||||
$( 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, "="),)?)*)*
|
||||||
};
|
};
|
||||||
f.write_str(s)
|
f.write_str(s)
|
||||||
}
|
}
|
||||||
|
@ -52,9 +53,10 @@ macro_rules! gen_token_kind {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn precedence(&self) -> Option<u8> {
|
pub fn precedence(&self) -> Option<u8> {
|
||||||
Some(match self {
|
Some(match self {
|
||||||
$($(Self::$op)|* => $prec,)*
|
$($(Self::$op => ${ignore($prec)} ${index(1)},
|
||||||
|
$(Self::$assign => 0,)?)*)*
|
||||||
_ => return None,
|
_ => return None,
|
||||||
})
|
} + 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
|
@ -64,6 +66,13 @@ 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)]
|
||||||
|
@ -71,7 +80,7 @@ macro_rules! gen_token_kind {
|
||||||
$( $pattern, )*
|
$( $pattern, )*
|
||||||
$( $keyword, )*
|
$( $keyword, )*
|
||||||
$( $punkt, )*
|
$( $punkt, )*
|
||||||
$($( $op, )*)*
|
$($( $op, $($assign,)? )*)*
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -106,24 +115,37 @@ gen_token_kind! {
|
||||||
Ctor = ".{",
|
Ctor = ".{",
|
||||||
Tupl = ".(",
|
Tupl = ".(",
|
||||||
#[ops]
|
#[ops]
|
||||||
#[prec = 1]
|
#[prec]
|
||||||
Decl = ":=",
|
Decl = ":=",
|
||||||
Assign = "=",
|
Assign = "=",
|
||||||
#[prec = 21]
|
#[prec]
|
||||||
|
Or = "||",
|
||||||
|
#[prec]
|
||||||
|
And = "&&",
|
||||||
|
#[prec]
|
||||||
|
Bor = "|" => BorAss,
|
||||||
|
#[prec]
|
||||||
|
Xor = "^" => XorAss,
|
||||||
|
#[prec]
|
||||||
|
Band = "&" => BandAss,
|
||||||
|
#[prec]
|
||||||
|
Eq = "==",
|
||||||
|
Ne = "!=",
|
||||||
|
#[prec]
|
||||||
Le = "<=",
|
Le = "<=",
|
||||||
Ge = ">=",
|
Ge = ">=",
|
||||||
Lt = "<",
|
Lt = "<",
|
||||||
Gt = ">",
|
Gt = ">",
|
||||||
Eq = "==",
|
#[prec]
|
||||||
Ne = "!=",
|
Shl = "<<" => ShlAss,
|
||||||
#[prec = 22]
|
Shr = ">>" => ShrAss,
|
||||||
Amp = "&",
|
#[prec]
|
||||||
#[prec = 23]
|
Add = "+" => AddAss,
|
||||||
Plus = "+",
|
Sub = "-" => SubAss,
|
||||||
Minus = "-",
|
#[prec]
|
||||||
#[prec = 24]
|
Mul = "*" => MulAss,
|
||||||
Star = "*",
|
Div = "/" => DivAss,
|
||||||
FSlash = "/",
|
Mod = "%" => ModAss,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -155,11 +177,92 @@ impl<'a> Lexer<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn next(&mut self) -> Token {
|
pub fn next(&mut self) -> Token {
|
||||||
Iterator::next(self).unwrap_or(Token {
|
use TokenKind as T;
|
||||||
kind: TokenKind::Eof,
|
loop {
|
||||||
start: self.pos,
|
let mut start = self.pos;
|
||||||
|
|
||||||
|
let Some(c) = self.advance() else {
|
||||||
|
return Token {
|
||||||
|
kind: T::Eof,
|
||||||
|
start,
|
||||||
end: self.pos,
|
end: self.pos,
|
||||||
})
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
let kind = match c {
|
||||||
|
b'\n' | b'\r' | b'\t' | b' ' => continue,
|
||||||
|
b'0'..=b'9' => {
|
||||||
|
while let Some(b'0'..=b'9') = self.peek() {
|
||||||
|
self.advance();
|
||||||
|
}
|
||||||
|
T::Number
|
||||||
|
}
|
||||||
|
c @ (b'a'..=b'z' | b'A'..=b'Z' | b'_' | b'@') => {
|
||||||
|
while let Some(b'a'..=b'z' | b'A'..=b'Z' | b'0'..=b'9' | b'_') = self.peek() {
|
||||||
|
self.advance();
|
||||||
|
}
|
||||||
|
|
||||||
|
if c == b'@' {
|
||||||
|
start += 1;
|
||||||
|
T::Driective
|
||||||
|
} else {
|
||||||
|
let ident = &self.bytes[start as usize..self.pos as usize];
|
||||||
|
T::from_ident(ident)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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::Tupl,
|
||||||
|
b'.' => T::Dot,
|
||||||
|
b';' => T::Semi,
|
||||||
|
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'&' => 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'|' => T::Bor,
|
||||||
|
b'(' => T::LParen,
|
||||||
|
b')' => T::RParen,
|
||||||
|
b'{' => T::LBrace,
|
||||||
|
b'}' => T::RBrace,
|
||||||
|
_ => T::Error,
|
||||||
|
};
|
||||||
|
|
||||||
|
return Token {
|
||||||
|
kind,
|
||||||
|
start,
|
||||||
|
end: self.pos,
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn advance_if(&mut self, arg: u8) -> bool {
|
fn advance_if(&mut self, arg: u8) -> bool {
|
||||||
|
@ -232,11 +335,11 @@ impl<'a> Iterator for Lexer<'a> {
|
||||||
b'<' => T::Lt,
|
b'<' => T::Lt,
|
||||||
b'>' if self.advance_if(b'=') => T::Ge,
|
b'>' if self.advance_if(b'=') => T::Ge,
|
||||||
b'>' => T::Gt,
|
b'>' => T::Gt,
|
||||||
b'+' => T::Plus,
|
b'+' => T::Add,
|
||||||
b'-' => T::Minus,
|
b'-' => T::Sub,
|
||||||
b'*' => T::Star,
|
b'*' => T::Mul,
|
||||||
b'/' => T::FSlash,
|
b'/' => T::Div,
|
||||||
b'&' => T::Amp,
|
b'&' => T::Band,
|
||||||
b'(' => T::LParen,
|
b'(' => T::LParen,
|
||||||
b')' => T::RParen,
|
b')' => T::RParen,
|
||||||
b'{' => T::LBrace,
|
b'{' => T::LBrace,
|
||||||
|
|
|
@ -74,7 +74,7 @@ impl<'a, 'b> Parser<'a, 'b> {
|
||||||
self.bin_expr(left, 0)
|
self.bin_expr(left, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn bin_expr(&mut self, mut left: Expr<'a>, min_prec: u8) -> Expr<'a> {
|
fn bin_expr(&mut self, mut fold: Expr<'a>, min_prec: u8) -> Expr<'a> {
|
||||||
loop {
|
loop {
|
||||||
let Some(prec) = self.token.kind.precedence() else {
|
let Some(prec) = self.token.kind.precedence() else {
|
||||||
break;
|
break;
|
||||||
|
@ -87,14 +87,22 @@ impl<'a, 'b> Parser<'a, 'b> {
|
||||||
let op = self.next().kind;
|
let op = self.next().kind;
|
||||||
let right = self.unit_expr();
|
let right = self.unit_expr();
|
||||||
let right = self.bin_expr(right, prec);
|
let right = self.bin_expr(right, prec);
|
||||||
left = Expr::BinOp {
|
let right = &*self.arena.alloc(right);
|
||||||
left: self.arena.alloc(left),
|
let left = &*self.arena.alloc(fold);
|
||||||
|
|
||||||
|
if let Some(op) = op.assign_op() {
|
||||||
|
let right = Expr::BinOp { left, op, right };
|
||||||
|
fold = Expr::BinOp {
|
||||||
|
left,
|
||||||
|
op: TokenKind::Assign,
|
||||||
right: self.arena.alloc(right),
|
right: self.arena.alloc(right),
|
||||||
op,
|
|
||||||
};
|
};
|
||||||
|
} else {
|
||||||
|
fold = Expr::BinOp { left, right, op };
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
left
|
fold
|
||||||
}
|
}
|
||||||
|
|
||||||
fn try_resolve_builtin(name: &str) -> Option<Ident> {
|
fn try_resolve_builtin(name: &str) -> Option<Ident> {
|
||||||
|
@ -220,7 +228,7 @@ impl<'a, 'b> Parser<'a, 'b> {
|
||||||
},
|
},
|
||||||
body: self.ptr_expr(),
|
body: self.ptr_expr(),
|
||||||
},
|
},
|
||||||
T::Amp | T::Star => E::UnOp {
|
T::Band | T::Mul => E::UnOp {
|
||||||
pos: token.start,
|
pos: token.start,
|
||||||
op: token.kind,
|
op: token.kind,
|
||||||
val: self.ptr_unit_expr(),
|
val: self.ptr_unit_expr(),
|
||||||
|
|
|
@ -8,23 +8,23 @@ Ident "int"
|
||||||
LBrace "{"
|
LBrace "{"
|
||||||
Return "return"
|
Return "return"
|
||||||
Number "10"
|
Number "10"
|
||||||
Minus "-"
|
Sub "-"
|
||||||
Number "20"
|
Number "20"
|
||||||
FSlash "/"
|
Div "/"
|
||||||
Number "2"
|
Number "2"
|
||||||
Plus "+"
|
Add "+"
|
||||||
Number "4"
|
Number "4"
|
||||||
Star "*"
|
Mul "*"
|
||||||
LParen "("
|
LParen "("
|
||||||
Number "2"
|
Number "2"
|
||||||
Plus "+"
|
Add "+"
|
||||||
Number "2"
|
Number "2"
|
||||||
RParen ")"
|
RParen ")"
|
||||||
Minus "-"
|
Sub "-"
|
||||||
Number "4"
|
Number "4"
|
||||||
Star "*"
|
Mul "*"
|
||||||
Number "4"
|
Number "4"
|
||||||
Plus "+"
|
Add "+"
|
||||||
Number "1"
|
Number "1"
|
||||||
Semi ";"
|
Semi ";"
|
||||||
RBrace "}"
|
RBrace "}"
|
||||||
|
|
Loading…
Reference in a new issue