prepare for modules

This commit is contained in:
2025-04-25 04:16:54 -04:00
parent 0ceb82445e
commit 4e7c201690
30 changed files with 369 additions and 333 deletions
+44 -25
View File
@@ -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 {
+6 -5
View File
@@ -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;
+3 -3
View File
@@ -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
View File
@@ -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,
}
}
}
-99
View File
@@ -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(())
}
}
+5 -17
View File
@@ -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;
+51 -6
View File
@@ -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),
}
}
}
+1 -2
View File
@@ -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,