adding framerk to add comments to different places

This commit is contained in:
mlokr 2024-09-14 12:27:53 +02:00
parent 3501ae58d8
commit bfeeff52cd
4 changed files with 137 additions and 64 deletions

View file

@ -150,6 +150,8 @@ drop := fn(a: int): void {
#### structs #### structs
```hb ```hb
Ty := struct { Ty := struct {
// comment
a: int, a: int,
b: int, b: int,
} }

View file

@ -5,7 +5,9 @@ use {
instrs::{self, *}, instrs::{self, *},
lexer::TokenKind, lexer::TokenKind,
log, log,
parser::{self, find_symbol, idfl, CtorField, Expr, ExprRef, FileId, Pos}, parser::{
self, find_symbol, idfl, CommentOr, CtorField, Expr, ExprRef, FileId, Pos, StructField,
},
ty, Field, Func, Global, LoggedMem, ParamAlloc, Reloc, Sig, Struct, SymKey, TypedReloc, ty, Field, Func, Global, LoggedMem, ParamAlloc, Reloc, Sig, Struct, SymKey, TypedReloc,
Types, Types,
}, },
@ -719,10 +721,11 @@ impl Codegen {
self.expr_ctx(expr, Ctx::default()) self.expr_ctx(expr, Ctx::default())
} }
fn build_struct(&mut self, fields: &[(&str, Expr)]) -> ty::Struct { fn build_struct(&mut self, fields: &[CommentOr<StructField>]) -> ty::Struct {
let fields = fields let fields = fields
.iter() .iter()
.map(|&(name, ty)| Field { name: name.into(), ty: self.ty(&ty) }) .filter_map(CommentOr::or)
.map(|sf| Field { name: sf.name.into(), ty: self.ty(&sf.ty) })
.collect(); .collect();
self.tys.structs.push(Struct { fields }); self.tys.structs.push(Struct { fields });
self.tys.structs.len() as u32 - 1 self.tys.structs.len() as u32 - 1

View file

@ -297,9 +297,18 @@ impl<'a, 'b> Parser<'a, 'b> {
self.ns_bound = self.idents.len(); self.ns_bound = self.idents.len();
self.expect_advance(T::LBrace); self.expect_advance(T::LBrace);
self.collect_list(T::Comma, T::RBrace, |s| { self.collect_list(T::Comma, T::RBrace, |s| {
let name = s.expect_advance(T::Ident); let tok = s.token;
s.expect_advance(T::Colon); if s.advance_if(T::Comment) {
(s.move_str(name), s.expr()) CommentOr::Comment { literal: s.move_str(tok), pos: tok.start }
} else {
let name = s.expect_advance(T::Ident);
s.expect_advance(T::Colon);
CommentOr::Or(StructField {
pos: name.start,
name: s.move_str(name),
ty: s.expr(),
})
}
}) })
}, },
captured: { captured: {
@ -350,6 +359,7 @@ impl<'a, 'b> Parser<'a, 'b> {
s.declare(name.start, id, None); s.declare(name.start, id, None);
s.expect_advance(T::Colon); s.expect_advance(T::Colon);
Arg { Arg {
pos: name.start,
name: s.move_str(name), name: s.move_str(name),
is_ct: name.kind == T::CtIdent, is_ct: name.kind == T::CtIdent,
id, id,
@ -578,6 +588,7 @@ pub fn find_symbol(symbols: &[Symbol], id: Ident) -> &Symbol {
#[derive(Debug, Clone, Copy, PartialEq, Eq)] #[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct Arg<'a> { pub struct Arg<'a> {
pub pos: u32,
pub name: &'a str, pub name: &'a str,
pub id: Ident, pub id: Ident,
pub is_ct: bool, pub is_ct: bool,
@ -585,6 +596,12 @@ pub struct Arg<'a> {
pub ty: Expr<'a>, pub ty: Expr<'a>,
} }
impl Poser for Arg<'_> {
fn posi(&self) -> Pos {
self.pos
}
}
macro_rules! generate_expr { macro_rules! generate_expr {
($(#[$meta:meta])* $vis:vis enum $name:ident<$lt:lifetime> {$( ($(#[$meta:meta])* $vis:vis enum $name:ident<$lt:lifetime> {$(
$(#[$field_meta:meta])* $(#[$field_meta:meta])*
@ -732,7 +749,7 @@ generate_expr! {
/// `'struct' LIST('{', ',', '}', Ident ':' Expr)` /// `'struct' LIST('{', ',', '}', Ident ':' Expr)`
Struct { Struct {
pos: Pos, pos: Pos,
fields: &'a [(&'a str, Self)], fields: &'a [CommentOr<'a, StructField<'a>>],
captured: &'a [Ident], captured: &'a [Ident],
trailing_comma: bool, trailing_comma: bool,
}, },
@ -833,6 +850,19 @@ impl<'a> Expr<'a> {
} }
} }
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub struct StructField<'a> {
pub pos: Pos,
pub name: &'a str,
pub ty: Expr<'a>,
}
impl Poser for StructField<'_> {
fn posi(&self) -> Pos {
self.pos
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)] #[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct CtorField<'a> { pub struct CtorField<'a> {
pub pos: Pos, pub pos: Pos,
@ -840,22 +870,52 @@ pub struct CtorField<'a> {
pub value: Expr<'a>, pub value: Expr<'a>,
} }
trait Poser { impl Poser for CtorField<'_> {
fn posi(self) -> Pos; fn posi(&self) -> Pos {
} self.pos
impl Poser for Pos {
fn posi(self) -> Pos {
self
} }
} }
impl<'a> Poser for &Expr<'a> { trait Poser {
fn posi(self) -> Pos { fn posi(&self) -> Pos;
}
impl Poser for Pos {
fn posi(&self) -> Pos {
*self
}
}
impl<'a> Poser for Expr<'a> {
fn posi(&self) -> Pos {
self.pos() self.pos()
} }
} }
impl<'a, T: Poser> Poser for CommentOr<'a, T> {
fn posi(&self) -> Pos {
match self {
CommentOr::Or(expr) => expr.posi(),
CommentOr::Comment { pos, .. } => *pos,
}
}
}
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub enum CommentOr<'a, T> {
Or(T),
Comment { literal: &'a str, pos: Pos },
}
impl<'a, T: Copy> CommentOr<'a, T> {
pub fn or(&self) -> Option<T> {
match *self {
CommentOr::Or(v) => Some(v),
CommentOr::Comment { .. } => None,
}
}
}
thread_local! { thread_local! {
static FMT_SOURCE: Cell<*const str> = const { Cell::new("") }; static FMT_SOURCE: Cell<*const str> = const { Cell::new("") };
} }
@ -874,20 +934,35 @@ impl<'a> fmt::Display for Expr<'a> {
static DISPLAY_BUFFER: Cell<String> = const { Cell::new(String::new()) }; static DISPLAY_BUFFER: Cell<String> = const { Cell::new(String::new()) };
} }
fn fmt_list<T>( fn fmt_list<T: Poser>(
f: &mut fmt::Formatter, f: &mut fmt::Formatter,
trailing: bool, trailing: bool,
end: &str, end: &str,
sep: &str,
list: &[T], list: &[T],
fmt: impl Fn(&T, &mut fmt::Formatter) -> fmt::Result, fmt: impl Fn(&T, &mut fmt::Formatter) -> fmt::Result,
) -> fmt::Result {
fmt_list_low(f, trailing, end, sep, list, |v, f| {
fmt(v, f)?;
Ok(true)
})
}
fn fmt_list_low<T: Poser>(
f: &mut fmt::Formatter,
trailing: bool,
end: &str,
sep: &str,
list: &[T],
fmt: impl Fn(&T, &mut fmt::Formatter) -> Result<bool, fmt::Error>,
) -> fmt::Result { ) -> fmt::Result {
if !trailing { if !trailing {
let first = &mut true; let mut first = true;
for expr in list { for expr in list {
if !std::mem::take(first) { if !std::mem::take(&mut first) {
write!(f, ", ")?; write!(f, "{sep} ")?;
} }
fmt(expr, f)?; first = !fmt(expr, f)?;
} }
return write!(f, "{end}"); return write!(f, "{end}");
} }
@ -895,12 +970,28 @@ impl<'a> fmt::Display for Expr<'a> {
writeln!(f)?; writeln!(f)?;
INDENT.with(|i| i.set(i.get() + 1)); INDENT.with(|i| i.set(i.get() + 1));
let res = (|| { let res = (|| {
for stmt in list { for (i, stmt) in list.iter().enumerate() {
for _ in 0..INDENT.with(|i| i.get()) { for _ in 0..INDENT.with(|i| i.get()) {
write!(f, "\t")?; write!(f, "\t")?;
} }
fmt(stmt, f)?; let add_sep = fmt(stmt, f)?;
writeln!(f, ",")?; if add_sep {
write!(f, "{sep}")?;
}
let source: &str = unsafe { &*FMT_SOURCE.with(|s| s.get()) };
if let Some(expr) = list.get(i + 1)
&& let Some(rest) = source.get(expr.posi() as usize..)
{
if insert_needed_semicolon(rest) {
write!(f, ";")?;
}
if preserve_newlines(&source[..expr.posi() as usize]) > 1 {
writeln!(f)?;
}
}
if add_sep {
writeln!(f)?;
}
} }
Ok(()) Ok(())
})(); })();
@ -937,8 +1028,6 @@ impl<'a> fmt::Display for Expr<'a> {
Consecutive => Expr::UnOp { .. }, Consecutive => Expr::UnOp { .. },
} }
let source: &str = unsafe { &*FMT_SOURCE.with(|s| s.get()) };
match *self { match *self {
Self::Ct { value, .. } => write!(f, "$: {}", value), Self::Ct { value, .. } => write!(f, "$: {}", value),
Self::String { literal, .. } => write!(f, "{}", literal), Self::String { literal, .. } => write!(f, "{}", literal),
@ -947,12 +1036,16 @@ impl<'a> fmt::Display for Expr<'a> {
Self::Field { target, name: field } => write!(f, "{}.{field}", Postfix(target)), Self::Field { target, name: field } => write!(f, "{}.{field}", Postfix(target)),
Self::Directive { name, args, .. } => { Self::Directive { name, args, .. } => {
write!(f, "@{name}(")?; write!(f, "@{name}(")?;
fmt_list(f, false, ")", args, fmt::Display::fmt) fmt_list(f, false, ")", ",", args, fmt::Display::fmt)
} }
Self::Struct { fields, trailing_comma, .. } => { Self::Struct { fields, trailing_comma, .. } => {
write!(f, "struct {{")?; write!(f, "struct {{")?;
fmt_list(f, trailing_comma, "}", fields, |(name, val), f| { fmt_list_low(f, trailing_comma, "}", ",", fields, |field, f| {
write!(f, "{name}: {val}",) match field {
CommentOr::Or(StructField { name, ty, .. }) => write!(f, "{name}: {ty}")?,
CommentOr::Comment { literal, .. } => write!(f, "{literal}")?,
}
Ok(field.or().is_some())
}) })
} }
Self::Ctor { ty, fields, trailing_comma, .. } => { Self::Ctor { ty, fields, trailing_comma, .. } => {
@ -967,14 +1060,14 @@ impl<'a> fmt::Display for Expr<'a> {
write!(f, "{name}: {value}") write!(f, "{name}: {value}")
} }
}; };
fmt_list(f, trailing_comma, "}", fields, fmt_field) fmt_list(f, trailing_comma, "}", ",", fields, fmt_field)
} }
Self::Tupl { ty, fields, trailing_comma, .. } => { Self::Tupl { ty, fields, trailing_comma, .. } => {
if let Some(ty) = ty { if let Some(ty) = ty {
write!(f, "{}", Unary(ty))?; write!(f, "{}", Unary(ty))?;
} }
write!(f, ".(")?; write!(f, ".(")?;
fmt_list(f, trailing_comma, ")", fields, fmt::Display::fmt) fmt_list(f, trailing_comma, ")", ",", fields, fmt::Display::fmt)
} }
Self::Slice { item, size, .. } => match size { Self::Slice { item, size, .. } => match size {
Some(size) => write!(f, "[{item}; {size}]"), Some(size) => write!(f, "[{item}; {size}]"),
@ -994,7 +1087,7 @@ impl<'a> fmt::Display for Expr<'a> {
Self::Loop { body, .. } => write!(f, "loop {body}"), Self::Loop { body, .. } => write!(f, "loop {body}"),
Self::Closure { ret, body, args, .. } => { Self::Closure { ret, body, args, .. } => {
write!(f, "fn(")?; write!(f, "fn(")?;
fmt_list(f, false, "", args, |arg, f| { fmt_list(f, false, "", ",", args, |arg, f| {
if arg.is_ct { if arg.is_ct {
write!(f, "$")?; write!(f, "$")?;
} }
@ -1005,7 +1098,7 @@ impl<'a> fmt::Display for Expr<'a> {
} }
Self::Call { func, args, trailing_comma } => { Self::Call { func, args, trailing_comma } => {
write!(f, "{}(", Postfix(func))?; write!(f, "{}(", Postfix(func))?;
fmt_list(f, trailing_comma, ")", args, fmt::Display::fmt) fmt_list(f, trailing_comma, ")", ",", args, fmt::Display::fmt)
} }
Self::Return { val: Some(val), .. } => write!(f, "return {val}"), Self::Return { val: Some(val), .. } => write!(f, "return {val}"),
Self::Return { val: None, .. } => write!(f, "return"), Self::Return { val: None, .. } => write!(f, "return"),
@ -1013,34 +1106,7 @@ impl<'a> fmt::Display for Expr<'a> {
Self::Ident { name, is_ct: false, .. } => write!(f, "{name}"), Self::Ident { name, is_ct: false, .. } => write!(f, "{name}"),
Self::Block { stmts, .. } => { Self::Block { stmts, .. } => {
write!(f, "{{")?; write!(f, "{{")?;
writeln!(f)?; fmt_list(f, true, "}", "", stmts, fmt::Display::fmt)
INDENT.with(|i| i.set(i.get() + 1));
let res = (|| {
for (i, stmt) in stmts.iter().enumerate() {
for _ in 0..INDENT.with(|i| i.get()) {
write!(f, "\t")?;
}
write!(f, "{stmt}")?;
if let Some(expr) = stmts.get(i + 1)
&& let Some(rest) = source.get(expr.pos() as usize..)
{
if insert_needed_semicolon(rest) {
write!(f, ";")?;
}
if preserve_newlines(&source[..expr.pos() as usize]) > 1 {
writeln!(f)?;
}
}
writeln!(f)?;
}
Ok(())
})();
INDENT.with(|i| i.set(i.get() - 1));
for _ in 0..INDENT.with(|i| i.get()) {
write!(f, "\t")?;
}
write!(f, "}}")?;
res
} }
Self::Number { value, radix, .. } => match radix { Self::Number { value, radix, .. } => match radix {
Radix::Decimal => write!(f, "{value}"), Radix::Decimal => write!(f, "{value}"),
@ -1080,6 +1146,7 @@ impl<'a> fmt::Display for Expr<'a> {
} }
}; };
let source: &str = unsafe { &*FMT_SOURCE.with(|s| s.get()) };
display_branch(f, left)?; display_branch(f, left)?;
if let Some(mut prev) = source.get(..right.pos() as usize) { if let Some(mut prev) = source.get(..right.pos() as usize) {
prev = prev.trim_end(); prev = prev.trim_end();

View file

@ -8,7 +8,7 @@ use {
parser::{ parser::{
self, self,
idfl::{self}, idfl::{self},
Expr, ExprRef, FileId, Pos, CommentOr, Expr, ExprRef, FileId, Pos, StructField,
}, },
task, ty, Field, Func, Reloc, Sig, Struct, SymKey, TypedReloc, Types, task, ty, Field, Func, Reloc, Sig, Struct, SymKey, TypedReloc, Types,
}, },
@ -1397,10 +1397,11 @@ impl Codegen {
self.expr_ctx(expr, Ctx::default()) self.expr_ctx(expr, Ctx::default())
} }
fn build_struct(&mut self, fields: &[(&str, Expr)]) -> ty::Struct { fn build_struct(&mut self, fields: &[CommentOr<StructField>]) -> ty::Struct {
let fields = fields let fields = fields
.iter() .iter()
.map(|&(name, ty)| Field { name: name.into(), ty: self.ty(&ty) }) .filter_map(CommentOr::or)
.map(|sf| Field { name: sf.name.into(), ty: self.ty(&sf.ty) })
.collect(); .collect();
self.tys.structs.push(Struct { fields }); self.tys.structs.push(Struct { fields });
self.tys.structs.len() as u32 - 1 self.tys.structs.len() as u32 - 1