start of ir
This commit is contained in:
@@ -19,6 +19,7 @@ fn main() {
|
||||
let a = 3;
|
||||
b
|
||||
};
|
||||
exit(3, let, "hello");
|
||||
}
|
||||
|
||||
fn test() {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
fn main() {
|
||||
let x = &"Hello World!";
|
||||
print(x);
|
||||
let x = 3;
|
||||
exit(x);
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ mod program;
|
||||
mod riscv64;
|
||||
mod target;
|
||||
|
||||
use program::*;
|
||||
pub use program::*;
|
||||
|
||||
pub fn main() {
|
||||
use std::io::prelude::*;
|
||||
|
||||
@@ -59,13 +59,13 @@ impl Deref for WritableSymbol {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct SymMap<I: Instr> {
|
||||
pub struct SymMap<I> {
|
||||
i: usize,
|
||||
ro_data: Vec<(Vec<u8>, Symbol)>,
|
||||
functions: Vec<(Vec<I>, Symbol)>,
|
||||
}
|
||||
|
||||
impl<I: Instr> SymMap<I> {
|
||||
impl<I> SymMap<I> {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
i: 0,
|
||||
|
||||
@@ -3,7 +3,13 @@ use crate::compiler::program::{Addr, Instr, SymTable, Symbol};
|
||||
use super::*;
|
||||
|
||||
pub enum AsmInstruction {
|
||||
Add(Reg, Reg, Reg),
|
||||
Addi(Reg, Reg, i32),
|
||||
Andi(Reg, Reg, i32),
|
||||
Slli(Reg, Reg, i32),
|
||||
Srli(Reg, Reg, i32),
|
||||
Sd(Reg, i32, Reg),
|
||||
Mv(Reg, Reg),
|
||||
La(Reg, Symbol),
|
||||
Jal(Reg, i32),
|
||||
Call(Symbol),
|
||||
@@ -16,7 +22,13 @@ pub enum AsmInstruction {
|
||||
impl Instr for AsmInstruction {
|
||||
fn push(&self, data: &mut Vec<u8>, sym_map: &SymTable, pos: Addr, missing: bool) -> Option<Symbol> {
|
||||
let last = match self {
|
||||
Self::Add(dest, src1, src2) => add(*dest, *src1, *src2),
|
||||
Self::Addi(dest, src, imm) => addi(*dest, *src, BitsI32::new(*imm)),
|
||||
Self::Andi(dest, src, imm) => andi(*dest, *src, BitsI32::new(*imm)),
|
||||
Self::Slli(dest, src, imm) => slli(*dest, *src, BitsI32::new(*imm)),
|
||||
Self::Srli(dest, src, imm) => srli(*dest, *src, BitsI32::new(*imm)),
|
||||
Self::Sd(src, offset, base) => sd(*src, BitsI32::new(*offset), *base),
|
||||
Self::Mv(dest, src) => addi(*dest, *src, BitsI32::new(0)),
|
||||
Self::La(dest, sym) => {
|
||||
if let Some(addr) = sym_map.get(*sym) {
|
||||
let offset = addr.val() as i32 - pos.val() as i32;
|
||||
|
||||
@@ -18,14 +18,14 @@ impl Instruction {
|
||||
pub type Funct3 = Bits32<2, 0>;
|
||||
|
||||
pub const fn r_type(
|
||||
funct7: u32,
|
||||
funct7: Bits32<6, 0>,
|
||||
rs2: Reg,
|
||||
rs1: Reg,
|
||||
funct3: Bits32<2, 0>,
|
||||
rd: Reg,
|
||||
opcode: u32,
|
||||
) -> I {
|
||||
I((funct7 << 25)
|
||||
I((funct7.val() << 25)
|
||||
+ (rs2.val() << 20)
|
||||
+ (rs1.val() << 15)
|
||||
+ (funct3.val() << 12)
|
||||
|
||||
@@ -31,9 +31,21 @@ pub const fn sw(src: Reg, offset: BitsI32<11, 0>, base: Reg) -> I {
|
||||
pub const fn sd(src: Reg, offset: BitsI32<11, 0>, base: Reg) -> I {
|
||||
s_type(src, base, width::D, offset.to_u(), STORE)
|
||||
}
|
||||
pub const fn add(dest: Reg, src1: Reg, src2: Reg) -> I {
|
||||
r_type(Bits32::new(0), src2, src1, ADD, dest, OP)
|
||||
}
|
||||
pub const fn addi(dest: Reg, src: Reg, imm: BitsI32<11, 0>) -> I {
|
||||
i_type(imm.to_u(), src, ADD, dest, IMM_OP)
|
||||
}
|
||||
pub const fn andi(dest: Reg, src: Reg, imm: BitsI32<11, 0>) -> I {
|
||||
i_type(imm.to_u(), src, AND, dest, IMM_OP)
|
||||
}
|
||||
pub const fn slli(dest: Reg, src: Reg, imm: BitsI32<4, 0>) -> I {
|
||||
i_type(Bits32::new(imm.to_u().val()), src, SLL, dest, IMM_OP)
|
||||
}
|
||||
pub const fn srli(dest: Reg, src: Reg, imm: BitsI32<4, 0>) -> I {
|
||||
i_type(Bits32::new(imm.to_u().val()), src, SR, dest, IMM_OP)
|
||||
}
|
||||
pub const fn jal(dest: Reg, offset: BitsI32<20, 1>) -> I {
|
||||
j_type(offset.to_u(), dest, JAL)
|
||||
}
|
||||
|
||||
126
src/ir/mod.rs
126
src/ir/mod.rs
@@ -1,2 +1,128 @@
|
||||
use std::collections::HashMap;
|
||||
|
||||
use crate::parser::{Body, Expr, Function, Ident, Literal, ParserError, Statement, Unresolved};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum IRInstruction {
|
||||
Li(IRIdent, Literal),
|
||||
Mv(IRIdent, IRIdent),
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct IRFunction {
|
||||
instructions: Vec<IRInstruction>,
|
||||
}
|
||||
|
||||
impl Function<Unresolved> {
|
||||
pub fn lower(&self, functions: &mut Vec<IRFunction>, map: &mut Namespace) -> Result<(), ParserError> {
|
||||
let Ok(name) = &self.name.inner else {
|
||||
return Ok(());
|
||||
};
|
||||
if map.get(name).is_some() {
|
||||
Err(ParserError {
|
||||
msg: format!("Already something named '{:?}'", self.name),
|
||||
spans: vec![self.name.span],
|
||||
})
|
||||
} else {
|
||||
map.add(name);
|
||||
let mut instructions = Vec::new();
|
||||
self.body.as_ref().map(|b| b.lower(map, &mut instructions));
|
||||
functions.push(IRFunction { instructions });
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Body<Unresolved> {
|
||||
pub fn lower(&self, map: &Namespace, instructions: &mut Vec<IRInstruction>) {
|
||||
let mut map = map.clone();
|
||||
for statement in &self.statements {
|
||||
let Ok(statement) = &statement.inner else {
|
||||
continue;
|
||||
};
|
||||
match statement {
|
||||
Statement::Let(name, expr) => {
|
||||
let Ok(name) = &name.inner else {
|
||||
continue;
|
||||
};
|
||||
let name = map.add(name);
|
||||
let Ok(expr) = &expr.inner else {
|
||||
continue;
|
||||
};
|
||||
if let Ok(Some(res)) = expr.lower(&map, instructions) {
|
||||
instructions.push(match res {
|
||||
ExprResult::Lit(l) => IRInstruction::Li(name, l),
|
||||
ExprResult::Ident(i) => IRInstruction::Mv(name, i),
|
||||
});
|
||||
}
|
||||
}
|
||||
Statement::Return(e) => todo!(),
|
||||
Statement::Expr(expr) => todo!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Expr<Unresolved> {
|
||||
pub fn lower(
|
||||
&self,
|
||||
map: &Namespace,
|
||||
instructions: &mut Vec<IRInstruction>,
|
||||
) -> Result<Option<ExprResult>, String> {
|
||||
Ok(match self {
|
||||
Expr::Lit(l) => {
|
||||
let Ok(l) = &l.inner else {return Ok(None)};
|
||||
Some(ExprResult::Lit(l.clone()))
|
||||
},
|
||||
Expr::Ident(i) => {
|
||||
let Ok(i) = &i.inner else {return Ok(None)};
|
||||
let Some(id) = map.get(i) else {
|
||||
return Err(format!("Identifier '{:?}' not found", i));
|
||||
};
|
||||
Some(ExprResult::Ident(id))
|
||||
}
|
||||
Expr::BinaryOp(_, _, _) => todo!(),
|
||||
Expr::UnaryOp(_, _) => todo!(),
|
||||
Expr::Block(_) => todo!(),
|
||||
Expr::Call(_, _) => todo!(),
|
||||
Expr::Group(_) => todo!(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
enum ExprResult {
|
||||
Lit(Literal),
|
||||
Ident(IRIdent),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Namespace {
|
||||
pub cur: usize,
|
||||
pub map: HashMap<String, IRIdent>,
|
||||
}
|
||||
|
||||
impl Namespace {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
cur: 0,
|
||||
map: HashMap::new(),
|
||||
}
|
||||
}
|
||||
pub fn get(&self, name: &Ident) -> Option<IRIdent> {
|
||||
self.map.get(name.val()).copied()
|
||||
}
|
||||
pub fn reserve(&mut self) -> IRIdent {
|
||||
let id = IRIdent ( self.cur );
|
||||
self.cur += 1;
|
||||
id
|
||||
}
|
||||
pub fn add(&mut self, name: &Ident) -> IRIdent {
|
||||
let id = self.reserve();
|
||||
self.map.insert(name.val().to_string(), id);
|
||||
id
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct IRIdent (usize);
|
||||
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
mod v1;
|
||||
mod v2;
|
||||
|
||||
pub use v1::*;
|
||||
|
||||
pub fn main() {
|
||||
let arg = std::env::args_os().nth(1);
|
||||
if let Some(path) = arg {
|
||||
|
||||
@@ -36,6 +36,14 @@ impl<'a> TokenCursor<'a> {
|
||||
.is_some_and(|n| n.token != Token::Symbol(symbol))
|
||||
{}
|
||||
}
|
||||
pub fn seek_syms(&mut self, syms: &[Symbol]) {
|
||||
while self
|
||||
.peek()
|
||||
.is_some_and(|n| !syms.iter().any(|s| n.is_symbol(*s)))
|
||||
{
|
||||
self.next();
|
||||
}
|
||||
}
|
||||
pub fn seek(&mut self, f: impl Fn(&TokenInstance) -> bool) -> Option<&TokenInstance> {
|
||||
loop {
|
||||
if f(self.peek()?) {
|
||||
@@ -53,13 +61,6 @@ impl<'a> TokenCursor<'a> {
|
||||
pub fn expect_peek(&mut self) -> Result<&TokenInstance, ParserError> {
|
||||
self.peek().ok_or(ParserError::unexpected_end())
|
||||
}
|
||||
pub fn expect_ident(&mut self) -> Result<String, ParserError> {
|
||||
let i = self.expect_next()?;
|
||||
let Token::Ident(n) = &i.token else {
|
||||
return Err(ParserError::unexpected_token(&i, "an identifier"));
|
||||
};
|
||||
Ok(n.to_string())
|
||||
}
|
||||
pub fn chars(&mut self) -> &mut CharCursor<'a> {
|
||||
&mut self.cursor
|
||||
}
|
||||
|
||||
@@ -7,13 +7,12 @@ use super::{
|
||||
use crate::util::Padder;
|
||||
|
||||
pub struct Body<R: MaybeResolved> {
|
||||
statements: Vec<Node<Statement<R>, R>>,
|
||||
pub statements: Vec<Node<Statement<R>, R>>,
|
||||
}
|
||||
|
||||
impl Parsable for Body<Unresolved> {
|
||||
fn parse(cursor: &mut TokenCursor, errors: &mut ParserErrors) -> ParseResult<Self> {
|
||||
let mut statements = Vec::new();
|
||||
let statement_end = &[Symbol::Semicolon, Symbol::CloseCurly];
|
||||
cursor.expect_sym(Symbol::OpenCurly)?;
|
||||
if cursor.expect_peek()?.is_symbol(Symbol::CloseCurly) {
|
||||
cursor.next();
|
||||
@@ -44,13 +43,12 @@ impl Parsable for Body<Unresolved> {
|
||||
let res = Statement::parse_node(cursor, errors);
|
||||
statements.push(res.node);
|
||||
expect_semi = true;
|
||||
if res.recover
|
||||
&& cursor
|
||||
.seek(|t| t.is_symbol_and(|s| statement_end.contains(&s)))
|
||||
.is_none()
|
||||
{
|
||||
recover = true;
|
||||
break;
|
||||
if res.recover {
|
||||
cursor.seek_syms(&[Symbol::Semicolon, Symbol::CloseCurly]);
|
||||
if cursor.peek().is_none() {
|
||||
recover = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
ParseResult::from_recover(Self { statements }, recover)
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
use std::fmt::{Debug, Write};
|
||||
|
||||
use super::token::{Symbol, Token};
|
||||
use super::{
|
||||
BinaryOperator, Body, Literal, MaybeResolved, Node, NodeParsable, Parsable, ParseResult,
|
||||
ParserError, ParserErrors, Resolvable, Resolved, TokenCursor, UnaryOperator, Unresolved,
|
||||
BinaryOperator, Body, Ident, Literal, MaybeResolved, Node, NodeParsable, Parsable, ParseResult,
|
||||
ParserError, ParserErrors, Resolvable, Resolved, Symbol, TokenCursor, UnaryOperator,
|
||||
Unresolved,
|
||||
};
|
||||
|
||||
type BoxNode<R> = Node<Box<Expr<R>>, R>;
|
||||
|
||||
pub enum Expr<R: MaybeResolved> {
|
||||
Lit(Node<Literal, R>),
|
||||
Ident(String),
|
||||
Ident(Node<Ident, R>),
|
||||
BinaryOp(BinaryOperator, BoxNode<R>, BoxNode<R>),
|
||||
UnaryOp(UnaryOperator, BoxNode<R>),
|
||||
Block(Node<Body<R>, R>),
|
||||
@@ -53,16 +53,12 @@ impl Parsable for Expr<Unresolved> {
|
||||
} else if let Some(val) = Node::maybe_parse(cursor, errors) {
|
||||
Self::Lit(val)
|
||||
} else {
|
||||
let next = cursor.peek().unwrap();
|
||||
match &next.token {
|
||||
Token::Ident(name) => {
|
||||
let name = name.to_string();
|
||||
cursor.next();
|
||||
Self::Ident(name)
|
||||
}
|
||||
_ => {
|
||||
return ParseResult::Err(ParserError::unexpected_token(next, "an expression"));
|
||||
}
|
||||
let res = Node::parse(cursor, &mut ParserErrors::new());
|
||||
if res.node.is_ok() {
|
||||
Self::Ident(res.node)
|
||||
} else {
|
||||
let next = cursor.expect_peek()?;
|
||||
return ParseResult::Err(ParserError::unexpected_token(next, "an expression"));
|
||||
}
|
||||
};
|
||||
let Some(mut next) = cursor.peek() else {
|
||||
@@ -71,13 +67,21 @@ impl Parsable for Expr<Unresolved> {
|
||||
while next.is_symbol(Symbol::OpenParen) {
|
||||
cursor.next();
|
||||
let mut args = Vec::new();
|
||||
while !cursor.expect_peek()?.is_symbol(Symbol::CloseParen) {
|
||||
loop {
|
||||
let next = cursor.expect_peek()?;
|
||||
if next.is_symbol(Symbol::CloseParen) {
|
||||
break;
|
||||
}
|
||||
let res = Node::<Expr<Unresolved>, Unresolved>::parse(cursor, errors);
|
||||
args.push(res.node);
|
||||
if res.recover {
|
||||
cursor.seek_sym(Symbol::CloseParen);
|
||||
cursor.seek_syms(&[Symbol::CloseParen, Symbol::Comma]);
|
||||
}
|
||||
let next = cursor.expect_peek()?;
|
||||
if !next.is_symbol(Symbol::Comma) {
|
||||
break;
|
||||
}
|
||||
cursor.next();
|
||||
}
|
||||
cursor.expect_sym(Symbol::CloseParen)?;
|
||||
let end = cursor.prev_end();
|
||||
@@ -118,7 +122,7 @@ impl Resolvable<Expr<Resolved>> for Expr<Unresolved> {
|
||||
fn resolve(self) -> Result<Expr<Resolved>, ()> {
|
||||
Ok(match self {
|
||||
Expr::Lit(l) => Expr::Lit(l.resolve()?),
|
||||
Expr::Ident(n) => Expr::Ident(n),
|
||||
Expr::Ident(n) => Expr::Ident(n.resolve()?),
|
||||
Expr::BinaryOp(o, e1, e2) => Expr::BinaryOp(o, e1.resolve()?, e2.resolve()?),
|
||||
Expr::UnaryOp(o, e) => Expr::UnaryOp(o, e.resolve()?),
|
||||
Expr::Block(b) => Expr::Block(b.resolve()?),
|
||||
@@ -137,7 +141,7 @@ impl Debug for Expr<Unresolved> {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
Expr::Lit(c) => c.fmt(f)?,
|
||||
Expr::Ident(n) => f.write_str(n)?,
|
||||
Expr::Ident(n) => n.fmt(f)?,
|
||||
Expr::Block(b) => b.fmt(f)?,
|
||||
Expr::BinaryOp(op, e1, e2) => {
|
||||
write!(f, "({:?}", *e1)?;
|
||||
|
||||
@@ -1,28 +1,28 @@
|
||||
use super::{
|
||||
Body, Keyword, MaybeResolved, Node, Parsable, ParseResult, ParserErrors, Resolvable, Resolved,
|
||||
Symbol, TokenCursor, Unresolved,
|
||||
Body, Ident, Keyword, MaybeResolved, Node, Parsable, ParseResult, ParserErrors, Resolvable,
|
||||
Resolved, Symbol, TokenCursor, Unresolved,
|
||||
};
|
||||
use std::fmt::Debug;
|
||||
|
||||
pub struct Function<R: MaybeResolved> {
|
||||
pub name: String,
|
||||
pub name: Node<Ident, R>,
|
||||
pub body: Node<Body<R>, R>,
|
||||
}
|
||||
|
||||
impl Parsable for Function<Unresolved> {
|
||||
fn parse(cursor: &mut TokenCursor, errors: &mut ParserErrors) -> ParseResult<Self> {
|
||||
cursor.expect_kw(Keyword::Fn)?;
|
||||
let name = cursor.expect_ident()?;
|
||||
let name = Node::parse(cursor, errors)?;
|
||||
cursor.expect_sym(Symbol::OpenParen)?;
|
||||
cursor.expect_sym(Symbol::CloseParen)?;
|
||||
Node::parse(cursor, errors).map(|body| Self {name, body})
|
||||
Node::parse(cursor, errors).map(|body| Self { name, body })
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for Function<Unresolved> {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
f.write_str("fn ")?;
|
||||
f.write_str(&self.name)?;
|
||||
self.name.fmt(f)?;
|
||||
f.write_str("() ")?;
|
||||
self.body.fmt(f)?;
|
||||
Ok(())
|
||||
@@ -32,7 +32,7 @@ impl Debug for Function<Unresolved> {
|
||||
impl Resolvable<Function<Resolved>> for Function<Unresolved> {
|
||||
fn resolve(self) -> Result<Function<Resolved>, ()> {
|
||||
Ok(Function {
|
||||
name: self.name,
|
||||
name: self.name.resolve()?,
|
||||
body: self.body.resolve()?,
|
||||
})
|
||||
}
|
||||
|
||||
34
src/parser/v1/nodes/ident.rs
Normal file
34
src/parser/v1/nodes/ident.rs
Normal file
@@ -0,0 +1,34 @@
|
||||
use std::fmt::Debug;
|
||||
use super::{Parsable, ParseResult, ParserError, Resolvable, Token};
|
||||
|
||||
pub struct Ident(String);
|
||||
|
||||
impl Ident {
|
||||
pub fn val(&self) -> &String {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl Parsable for Ident {
|
||||
fn parse(cursor: &mut super::TokenCursor, errors: &mut super::ParserErrors) -> ParseResult<Self> {
|
||||
let next = cursor.expect_peek()?;
|
||||
let Token::Ident(name) = &next.token else {
|
||||
return ParseResult::Err(ParserError::unexpected_token(next, "an identifier"));
|
||||
};
|
||||
let name = name.to_string();
|
||||
cursor.next();
|
||||
ParseResult::Ok(Self(name))
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for Ident {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "{}", self.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl Resolvable<Ident> for Ident {
|
||||
fn resolve(self) -> Result<Ident, ()> {
|
||||
Ok(self)
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,6 @@
|
||||
use super::{CharCursor, MaybeParsable, ParserError, ParserErrors, Resolvable, Symbol, Token, TokenCursor};
|
||||
use super::{
|
||||
CharCursor, MaybeParsable, ParserError, ParserErrors, Resolvable, Symbol, Token, TokenCursor,
|
||||
};
|
||||
use std::fmt::Debug;
|
||||
|
||||
#[derive(Clone, PartialEq, Eq)]
|
||||
@@ -17,7 +19,10 @@ pub struct Number {
|
||||
}
|
||||
|
||||
impl MaybeParsable for Literal {
|
||||
fn maybe_parse(cursor: &mut TokenCursor, _: &mut ParserErrors) -> Result<Option<Self>, ParserError> {
|
||||
fn maybe_parse(
|
||||
cursor: &mut TokenCursor,
|
||||
_: &mut ParserErrors,
|
||||
) -> Result<Option<Self>, ParserError> {
|
||||
let inst = cursor.expect_peek()?;
|
||||
let mut res = match &inst.token {
|
||||
Token::Symbol(Symbol::SingleQuote) => {
|
||||
@@ -42,15 +47,14 @@ impl MaybeParsable for Literal {
|
||||
_ => return Ok(None),
|
||||
};
|
||||
cursor.next();
|
||||
if let Some(next) = cursor.peek() {
|
||||
if let Self::Number(num) = &mut res {
|
||||
if let Token::Symbol(Symbol::Dot) = next.token {
|
||||
let chars = cursor.chars();
|
||||
if let Some(c) = chars.peek() {
|
||||
if c.is_ascii_digit() {
|
||||
if let (Some(next), Self::Number(num)) = (cursor.peek(), &mut res) {
|
||||
if next.token.is_symbol(Symbol::Dot) {
|
||||
cursor.next();
|
||||
if let Some(next) = cursor.peek() {
|
||||
if let Token::Ident(i) = &next.token {
|
||||
if i.chars().next().unwrap().is_ascii_digit() {
|
||||
num.decimal = Some(i.to_string());
|
||||
cursor.next();
|
||||
let decimal = cursor.expect_ident()?;
|
||||
num.decimal = Some(decimal);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -114,4 +118,3 @@ impl Debug for Number {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,8 @@ mod func;
|
||||
mod module;
|
||||
mod op;
|
||||
mod statement;
|
||||
mod val;
|
||||
mod lit;
|
||||
mod ident;
|
||||
|
||||
pub use body::*;
|
||||
pub use expr::*;
|
||||
@@ -12,6 +13,7 @@ pub use func::*;
|
||||
pub use module::*;
|
||||
pub use op::*;
|
||||
pub use statement::*;
|
||||
pub use val::*;
|
||||
pub use lit::*;
|
||||
pub use ident::*;
|
||||
|
||||
use super::*;
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
use std::fmt::{Debug, Write};
|
||||
use super::{
|
||||
Expr, Keyword, MaybeResolved, Node, Parsable, ParseResult, ParserErrors, Resolvable, Resolved, Symbol, Token, TokenCursor, Unresolved
|
||||
Expr, Ident, Keyword, MaybeResolved, Node, Parsable, ParseResult, ParserErrors, Resolvable, Resolved, Symbol, Token, TokenCursor, Unresolved
|
||||
};
|
||||
|
||||
pub enum Statement<R: MaybeResolved> {
|
||||
Let(String, Node<Expr<R>, R>),
|
||||
Let(Node<Ident, R>, Node<Expr<R>, R>),
|
||||
Return(Node<Expr<R>, R>),
|
||||
Expr(Node<Expr<R>, R>),
|
||||
}
|
||||
@@ -15,7 +15,7 @@ impl Parsable for Statement<Unresolved> {
|
||||
match next.token {
|
||||
Token::Keyword(Keyword::Let) => {
|
||||
cursor.next();
|
||||
let name = cursor.expect_ident()?;
|
||||
let name = Node::parse(cursor, errors)?;
|
||||
cursor.expect_sym(Symbol::Equals)?;
|
||||
Node::parse(cursor, errors).map(|expr| Self::Let(name, expr))
|
||||
}
|
||||
@@ -31,7 +31,7 @@ impl Parsable for Statement<Unresolved> {
|
||||
impl Resolvable<Statement<Resolved>> for Statement<Unresolved> {
|
||||
fn resolve(self) -> Result<Statement<Resolved>, ()> {
|
||||
Ok(match self {
|
||||
Self::Let(i, e) => Statement::Let(i, e.resolve()?),
|
||||
Self::Let(i, e) => Statement::Let(i.resolve()?, e.resolve()?),
|
||||
Self::Return(e) => Statement::Return(e.resolve()?),
|
||||
Self::Expr(e) => Statement::Expr(e.resolve()?),
|
||||
})
|
||||
@@ -43,7 +43,7 @@ impl Debug for Statement<Unresolved> {
|
||||
match self {
|
||||
Statement::Let(n, e) => {
|
||||
f.write_str("let ")?;
|
||||
f.write_str(n)?;
|
||||
n.fmt(f);
|
||||
f.write_str(" = ")?;
|
||||
e.fmt(f)?;
|
||||
f.write_char(';')?;
|
||||
|
||||
@@ -68,17 +68,6 @@ impl<T, U> FromResidual<ParseResult<T>> for ParseResult<U> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> ParseResult<T> {
|
||||
pub fn map<U, F: FnOnce(T) -> U>(self, op: F) -> ParseResult<U> {
|
||||
match self {
|
||||
Self::Ok(v) => ParseResult::Ok(op(v)),
|
||||
Self::Recover(v) => ParseResult::Recover(op(v)),
|
||||
Self::Err(e) => ParseResult::Err(e),
|
||||
Self::SubErr => ParseResult::SubErr,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct NodeParseResult<T> {
|
||||
pub node: Node<T, Unresolved>,
|
||||
pub recover: bool,
|
||||
@@ -116,8 +105,8 @@ impl<T> Try for NodeParseResult<T> {
|
||||
}
|
||||
|
||||
impl<T> FromResidual for NodeParseResult<T> {
|
||||
fn from_residual(residual: <Self as Try>::Residual) -> Self {
|
||||
// ???
|
||||
fn from_residual(_: <Self as Try>::Residual) -> Self {
|
||||
// I hope this is unreachable ???
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,6 +32,7 @@ pub enum Symbol {
|
||||
DoubleAmpersand,
|
||||
Pipe,
|
||||
DoublePipe,
|
||||
Comma,
|
||||
}
|
||||
|
||||
impl Symbol {
|
||||
@@ -65,6 +66,7 @@ impl Symbol {
|
||||
'!' => Self::Bang,
|
||||
'&' => Self::Ampersand,
|
||||
'|' => Self::Pipe,
|
||||
',' => Self::Comma,
|
||||
_ => return None,
|
||||
})
|
||||
}
|
||||
@@ -93,11 +95,11 @@ impl Symbol {
|
||||
Self::Ampersand => match next {
|
||||
'&' => Self::DoubleAmpersand,
|
||||
_ => return,
|
||||
}
|
||||
},
|
||||
Self::Pipe => match next {
|
||||
'&' => Self::DoublePipe,
|
||||
_ => return,
|
||||
}
|
||||
},
|
||||
_ => return,
|
||||
};
|
||||
cursor.advance();
|
||||
@@ -128,6 +130,7 @@ impl Symbol {
|
||||
Self::SingleQuote => "'",
|
||||
Self::DoubleQuote => "\"",
|
||||
Self::Bang => "!",
|
||||
Self::Comma => ",",
|
||||
Self::Ampersand => "&",
|
||||
Self::DoubleAmpersand => "&&",
|
||||
Self::Pipe => "|",
|
||||
|
||||
Reference in New Issue
Block a user