prepare for modules
This commit is contained in:
@@ -1,33 +1,41 @@
|
||||
use std::fmt::{Debug, Write};
|
||||
|
||||
use super::{
|
||||
token::Symbol, Node, NodeParsable, PStatement, Parsable, ParseResult, ParserCtx, CompilerMsg,
|
||||
token::Symbol, CompilerMsg, Node, NodeParsable, PStatementLike, ParseResult, ParserCtx,
|
||||
};
|
||||
use crate::{
|
||||
parser::{ParsableWith, TokenInstance},
|
||||
util::Padder,
|
||||
};
|
||||
use crate::util::Padder;
|
||||
|
||||
pub struct PBlock {
|
||||
pub statements: Vec<Node<PStatement>>,
|
||||
pub result: Option<Node<Box<PStatement>>>,
|
||||
pub statements: Vec<Node<PStatementLike>>,
|
||||
pub ret_last: bool,
|
||||
}
|
||||
|
||||
impl Parsable for PBlock {
|
||||
fn parse(ctx: &mut ParserCtx) -> ParseResult<Self> {
|
||||
impl ParsableWith for PBlock {
|
||||
type Data = Option<Symbol>;
|
||||
fn parse(ctx: &mut ParserCtx, end: Option<Symbol>) -> ParseResult<Self> {
|
||||
let mut statements = Vec::new();
|
||||
let mut result = None;
|
||||
ctx.expect_sym(Symbol::OpenCurly)?;
|
||||
if ctx.expect_peek()?.is_symbol(Symbol::CloseCurly) {
|
||||
let is_end = |t: &TokenInstance| -> bool { end.map(|e| t.is_symbol(e)).unwrap_or(false) };
|
||||
if ctx.peek().is_none_or(is_end) {
|
||||
ctx.next();
|
||||
return ParseResult::Ok(Self { statements, result });
|
||||
return ParseResult::Ok(Self {
|
||||
statements,
|
||||
ret_last: false,
|
||||
});
|
||||
}
|
||||
let mut expect_semi = false;
|
||||
let mut recover = false;
|
||||
loop {
|
||||
let Some(next) = ctx.peek() else {
|
||||
recover = true;
|
||||
ctx.err(CompilerMsg::unexpected_end());
|
||||
if end.is_some() {
|
||||
recover = true;
|
||||
ctx.err(CompilerMsg::unexpected_end());
|
||||
}
|
||||
break;
|
||||
};
|
||||
if next.is_symbol(Symbol::CloseCurly) {
|
||||
if is_end(next) {
|
||||
ctx.next();
|
||||
break;
|
||||
}
|
||||
@@ -41,9 +49,12 @@ impl Parsable for PBlock {
|
||||
spans: vec![ctx.next_start().char_span()],
|
||||
});
|
||||
}
|
||||
let res = PStatement::parse_node(ctx);
|
||||
let res = PStatementLike::parse_node(ctx);
|
||||
expect_semi = res
|
||||
.node
|
||||
.as_ref()
|
||||
.is_some_and(|s| matches!(s, PStatementLike::Statement(..)));
|
||||
statements.push(res.node);
|
||||
expect_semi = true;
|
||||
if res.recover {
|
||||
ctx.seek_syms(&[Symbol::Semicolon, Symbol::CloseCurly]);
|
||||
if ctx.peek().is_none() {
|
||||
@@ -52,26 +63,34 @@ impl Parsable for PBlock {
|
||||
}
|
||||
}
|
||||
}
|
||||
if expect_semi {
|
||||
if let Some(s) = statements.pop() {
|
||||
result = Some(s.bx());
|
||||
}
|
||||
}
|
||||
ParseResult::from_recover(Self { statements, result }, recover)
|
||||
ParseResult::from_recover(
|
||||
Self {
|
||||
statements,
|
||||
ret_last: expect_semi,
|
||||
},
|
||||
recover,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for PBlock {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
if !self.statements.is_empty() || self.result.is_some() {
|
||||
if !self.statements.is_empty() {
|
||||
f.write_str("{\n ")?;
|
||||
let mut padder = Padder::new(f);
|
||||
for s in &self.statements {
|
||||
let mut end = self.statements.len();
|
||||
if self.ret_last {
|
||||
end -= 1;
|
||||
}
|
||||
for i in 0..end {
|
||||
let s = &self.statements[i];
|
||||
// they don't expose wrap_buf :grief:
|
||||
padder.write_str(&format!("{s:?};\n"))?;
|
||||
}
|
||||
if let Some(res) = &self.result {
|
||||
padder.write_str(&format!("{res:?}\n"))?;
|
||||
if self.ret_last
|
||||
&& let Some(s) = self.statements.last()
|
||||
{
|
||||
padder.write_str(&format!("{s:?}\n"))?;
|
||||
}
|
||||
f.write_char('}')?;
|
||||
} else {
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
use std::fmt::{Debug, Write};
|
||||
|
||||
use crate::common::FilePos;
|
||||
use crate::{common::FilePos, parser::NodeParsableWith};
|
||||
|
||||
use super::{
|
||||
op::{PInfixOp, UnaryOp},
|
||||
util::parse_list,
|
||||
CompilerMsg, Keyword, Node, NodeParsable, PAsmBlock, PBlock, PConstruct, PIdent, PLiteral,
|
||||
CompilerMsg, Keyword, Node, PAsmBlock, PBlock, PConstruct, PIdent, PLiteral,
|
||||
Parsable, ParseResult, ParserCtx, Symbol,
|
||||
};
|
||||
|
||||
@@ -47,7 +47,8 @@ impl Parsable for PExpr {
|
||||
ctx.expect_sym(Symbol::CloseParen)?;
|
||||
Self::Group(res.node.bx())
|
||||
} else if next.is_symbol(Symbol::OpenCurly) {
|
||||
Self::Block(PBlock::parse_node(ctx)?)
|
||||
ctx.next();
|
||||
Self::Block(PBlock::parse_node(ctx, Some(Symbol::CloseCurly))?)
|
||||
} else if next.is_keyword(Keyword::If) {
|
||||
ctx.next();
|
||||
let cond = ctx.parse()?.bx();
|
||||
@@ -71,7 +72,7 @@ impl Parsable for PExpr {
|
||||
return ctx.parse().map(|n| {
|
||||
let n = n.bx();
|
||||
if let Some(box Self::BinaryOp(op2, n1, n2)) = n.inner {
|
||||
let span = start.to(n1.span.end);
|
||||
let span = start.to(n1.origin.end);
|
||||
Self::BinaryOp(op2, Node::new(Self::UnaryOp(op, n1), span).bx(), n2)
|
||||
} else {
|
||||
Self::UnaryOp(op, n)
|
||||
@@ -138,7 +139,7 @@ pub fn fix_precedence(
|
||||
let Some(box PExpr::BinaryOp(op2, n21, n22)) = n2.inner else {
|
||||
unreachable!();
|
||||
};
|
||||
let span = start.to(n21.span.end);
|
||||
let span = start.to(n21.origin.end);
|
||||
let (n11, op1, n12) = fix_precedence(n1, op, n21, start);
|
||||
n1 = Node::new(PExpr::BinaryOp(op1, n11, n12), span).bx();
|
||||
op = op2;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use super::{
|
||||
util::parse_list, PBlock, PIdent, Keyword, Node, Parsable, ParseResult, ParserCtx,
|
||||
util::parse_list, PBlock, PIdent, Node, Parsable, ParseResult, ParserCtx,
|
||||
Symbol, PType, PVarDef,
|
||||
};
|
||||
use std::fmt::Debug;
|
||||
@@ -17,7 +17,6 @@ pub struct PFunction {
|
||||
|
||||
impl Parsable for PFunctionHeader {
|
||||
fn parse(ctx: &mut ParserCtx) -> ParseResult<Self> {
|
||||
ctx.expect_kw(Keyword::Fn)?;
|
||||
let name = ctx.parse()?;
|
||||
ctx.expect_sym(Symbol::OpenParen)?;
|
||||
// let sel = ctx.maybe_parse();
|
||||
@@ -48,7 +47,8 @@ impl Parsable for PFunctionHeader {
|
||||
impl Parsable for PFunction {
|
||||
fn parse(ctx: &mut ParserCtx) -> ParseResult<Self> {
|
||||
let header = ctx.parse()?;
|
||||
let body = ctx.parse()?;
|
||||
ctx.expect_sym(Symbol::OpenCurly)?;
|
||||
let body = ctx.parse_with(Some(Symbol::CloseCurly))?;
|
||||
ParseResult::Ok(Self { header, body })
|
||||
}
|
||||
}
|
||||
|
||||
+30
-19
@@ -1,35 +1,46 @@
|
||||
mod asm_block;
|
||||
mod asm_fn;
|
||||
mod asm_instr;
|
||||
mod block;
|
||||
mod def;
|
||||
mod expr;
|
||||
mod func;
|
||||
mod module;
|
||||
mod ident;
|
||||
mod lit;
|
||||
mod op;
|
||||
mod statement;
|
||||
mod lit;
|
||||
mod ident;
|
||||
mod ty;
|
||||
mod def;
|
||||
mod struc;
|
||||
mod util;
|
||||
mod trai;
|
||||
mod asm_fn;
|
||||
mod asm_block;
|
||||
mod asm_instr;
|
||||
mod ty;
|
||||
mod util;
|
||||
|
||||
pub use asm_block::*;
|
||||
pub use asm_fn::*;
|
||||
pub use asm_instr::*;
|
||||
pub use block::*;
|
||||
pub use def::*;
|
||||
pub use expr::*;
|
||||
pub use func::*;
|
||||
pub use module::*;
|
||||
pub use statement::*;
|
||||
pub use lit::*;
|
||||
pub use ident::*;
|
||||
pub use ty::*;
|
||||
pub use def::*;
|
||||
pub use lit::*;
|
||||
pub use op::*;
|
||||
pub use statement::*;
|
||||
pub use struc::*;
|
||||
pub use trai::*;
|
||||
pub use op::*;
|
||||
pub use asm_fn::*;
|
||||
pub use asm_block::*;
|
||||
pub use asm_instr::*;
|
||||
pub use ty::*;
|
||||
|
||||
use crate::ir::UProgram;
|
||||
|
||||
use super::*;
|
||||
use super::{lower::{FnLowerCtx, FnLowerable}, *};
|
||||
|
||||
pub struct PModule {
|
||||
pub block: Node<PBlock>,
|
||||
}
|
||||
|
||||
impl PModule {
|
||||
pub fn parse(ctx: &mut ParserCtx) -> Self {
|
||||
Self {
|
||||
block: PBlock::parse_node(ctx, None).node,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,99 +0,0 @@
|
||||
use super::{
|
||||
PFunction, PImpl, Keyword, Node, Parsable, ParseResult, ParserCtx, CompilerMsg,
|
||||
PStruct, Symbol, Token, PTrait,
|
||||
};
|
||||
use std::fmt::Debug;
|
||||
|
||||
pub struct PModule {
|
||||
pub traits: Vec<Node<PTrait>>,
|
||||
pub structs: Vec<Node<PStruct>>,
|
||||
pub functions: Vec<Node<PFunction>>,
|
||||
pub impls: Vec<Node<PImpl>>,
|
||||
}
|
||||
|
||||
impl Parsable for PModule {
|
||||
fn parse(ctx: &mut ParserCtx) -> ParseResult<Self> {
|
||||
let mut functions = Vec::new();
|
||||
let mut structs = Vec::new();
|
||||
let mut traits = Vec::new();
|
||||
let mut impls = Vec::new();
|
||||
loop {
|
||||
let Some(next) = ctx.peek() else {
|
||||
break;
|
||||
};
|
||||
if let Token::Keyword(kw) = next.token {
|
||||
match kw {
|
||||
Keyword::Fn => {
|
||||
let res = ctx.parse();
|
||||
functions.push(res.node);
|
||||
if res.recover {
|
||||
break;
|
||||
}
|
||||
}
|
||||
Keyword::Struct => {
|
||||
let res = ctx.parse();
|
||||
structs.push(res.node);
|
||||
if res.recover {
|
||||
break;
|
||||
}
|
||||
}
|
||||
Keyword::Trait => {
|
||||
let res = ctx.parse();
|
||||
traits.push(res.node);
|
||||
if res.recover {
|
||||
break;
|
||||
}
|
||||
}
|
||||
Keyword::Impl => {
|
||||
let res = ctx.parse();
|
||||
impls.push(res.node);
|
||||
if res.recover {
|
||||
break;
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
ctx.err(CompilerMsg::unexpected_token(next, "a definition"));
|
||||
ctx.next();
|
||||
}
|
||||
}
|
||||
} else if next.is_symbol(Symbol::Semicolon) {
|
||||
ctx.hint(CompilerMsg::from_instances(
|
||||
&[next],
|
||||
"unneeded semicolon".to_string(),
|
||||
));
|
||||
ctx.next();
|
||||
} else {
|
||||
ctx.err(CompilerMsg::unexpected_token(next, "a definition"));
|
||||
ctx.next();
|
||||
}
|
||||
}
|
||||
ParseResult::Ok(Self {
|
||||
functions,
|
||||
structs,
|
||||
traits,
|
||||
impls,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for PModule {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
for st in &self.structs {
|
||||
st.fmt(f)?;
|
||||
writeln!(f)?;
|
||||
}
|
||||
for t in &self.traits {
|
||||
t.fmt(f)?;
|
||||
writeln!(f)?;
|
||||
}
|
||||
for t in &self.impls {
|
||||
t.fmt(f)?;
|
||||
writeln!(f)?;
|
||||
}
|
||||
for func in &self.functions {
|
||||
func.fmt(f)?;
|
||||
writeln!(f)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@@ -8,7 +8,7 @@ pub enum PInfixOp {
|
||||
Div,
|
||||
LessThan,
|
||||
GreaterThan,
|
||||
Access,
|
||||
Member,
|
||||
Assign,
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ impl PInfixOp {
|
||||
Self::Sub => 3,
|
||||
Self::Mul => 4,
|
||||
Self::Div => 5,
|
||||
Self::Access => 6,
|
||||
Self::Member => 6,
|
||||
}
|
||||
}
|
||||
pub fn str(&self) -> &str {
|
||||
@@ -33,7 +33,7 @@ impl PInfixOp {
|
||||
Self::Div => "/",
|
||||
Self::LessThan => "<",
|
||||
Self::GreaterThan => ">",
|
||||
Self::Access => ".",
|
||||
Self::Member => ".",
|
||||
Self::Assign => "=",
|
||||
}
|
||||
}
|
||||
@@ -45,22 +45,10 @@ impl PInfixOp {
|
||||
Self::Div => true,
|
||||
Self::LessThan => true,
|
||||
Self::GreaterThan => true,
|
||||
Self::Access => false,
|
||||
Self::Member => false,
|
||||
Self::Assign => true,
|
||||
}
|
||||
}
|
||||
pub fn traitt(&self) -> &str {
|
||||
match self {
|
||||
Self::Add => "Add",
|
||||
Self::Sub => "Sub",
|
||||
Self::Mul => "Mul",
|
||||
Self::Div => "Div",
|
||||
Self::LessThan => "LessThan",
|
||||
Self::GreaterThan => "GreaterThan",
|
||||
Self::Access => "Access",
|
||||
Self::Assign => "Assign",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub enum UnaryOp {
|
||||
@@ -81,7 +69,7 @@ impl PInfixOp {
|
||||
Symbol::Minus => Self::Sub,
|
||||
Symbol::Asterisk => Self::Mul,
|
||||
Symbol::Slash => Self::Div,
|
||||
Symbol::Dot => Self::Access,
|
||||
Symbol::Dot => Self::Member,
|
||||
Symbol::Equals => Self::Assign,
|
||||
_ => {
|
||||
return None;
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
use super::{Keyword, Node, PExpr, PVarDef, Parsable, ParseResult, ParserCtx, Symbol, Token};
|
||||
use super::{
|
||||
Keyword, Node, PExpr, PFunction, PStruct, PVarDef, Parsable, ParseResult, ParserCtx, Symbol,
|
||||
Token,
|
||||
};
|
||||
|
||||
pub enum PStatement {
|
||||
Let(Node<PVarDef>, Node<PExpr>),
|
||||
@@ -6,7 +9,17 @@ pub enum PStatement {
|
||||
Expr(Node<PExpr>),
|
||||
}
|
||||
|
||||
impl Parsable for PStatement {
|
||||
pub enum PConstStatement {
|
||||
Fn(Node<PFunction>),
|
||||
Struct(Node<PStruct>),
|
||||
}
|
||||
|
||||
pub enum PStatementLike {
|
||||
Statement(PStatement),
|
||||
Const(PConstStatement),
|
||||
}
|
||||
|
||||
impl Parsable for PStatementLike {
|
||||
fn parse(ctx: &mut ParserCtx) -> ParseResult<Self> {
|
||||
let next = ctx.expect_peek()?;
|
||||
match next.token {
|
||||
@@ -14,17 +27,27 @@ impl Parsable for PStatement {
|
||||
ctx.next();
|
||||
let def = ctx.parse()?;
|
||||
ctx.expect_sym(Symbol::Equals)?;
|
||||
ctx.parse().map(|expr| Self::Let(def, expr))
|
||||
ctx.parse()
|
||||
.map(|expr| Self::Statement(PStatement::Let(def, expr)))
|
||||
}
|
||||
Token::Keyword(Keyword::Return) => {
|
||||
ctx.next();
|
||||
if ctx.peek().is_some_and(|t| t.is_symbol(Symbol::Semicolon)) {
|
||||
ParseResult::Ok(Self::Return(None))
|
||||
ParseResult::Ok(Self::Statement(PStatement::Return(None)))
|
||||
} else {
|
||||
ctx.parse().map(|res| Self::Return(Some(res)))
|
||||
ctx.parse()
|
||||
.map(|res| Self::Statement(PStatement::Return(Some(res))))
|
||||
}
|
||||
}
|
||||
_ => ctx.parse().map(Self::Expr),
|
||||
Token::Keyword(Keyword::Fn) => {
|
||||
ctx.next();
|
||||
ParseResult::Ok(Self::Const(PConstStatement::Fn(ctx.parse()?)))
|
||||
}
|
||||
Token::Keyword(Keyword::Struct) => {
|
||||
ctx.next();
|
||||
ParseResult::Ok(Self::Const(PConstStatement::Struct(ctx.parse()?)))
|
||||
}
|
||||
_ => ctx.parse().map(|n| Self::Statement(PStatement::Expr(n))),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -49,3 +72,25 @@ impl std::fmt::Debug for PStatement {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
impl std::fmt::Debug for PConstStatement {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
Self::Fn(fun) => {
|
||||
fun.fmt(f)?;
|
||||
}
|
||||
Self::Struct(s) => {
|
||||
s.fmt(f)?;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Debug for PStatementLike {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
Self::Statement(s) => s.fmt(f),
|
||||
Self::Const(c) => c.fmt(f),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,7 +36,6 @@ pub enum PConstructFields {
|
||||
|
||||
impl Parsable for PStruct {
|
||||
fn parse(ctx: &mut ParserCtx) -> ParseResult<Self> {
|
||||
ctx.expect_kw(Keyword::Struct)?;
|
||||
let name = ctx.parse()?;
|
||||
let mut next = ctx.expect_peek()?;
|
||||
let args = if next.is_symbol(Symbol::OpenAngle) {
|
||||
@@ -75,7 +74,7 @@ impl ParsableWith for PConstruct {
|
||||
let next = ctx.expect_peek()?;
|
||||
// TODO: this is not correct span; type should also span generics, which aren't even in
|
||||
// here yet
|
||||
let span = name_node.span;
|
||||
let span = name_node.origin;
|
||||
let name = Node::new(
|
||||
PType {
|
||||
name: name_node,
|
||||
|
||||
Reference in New Issue
Block a user