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
```hb
Ty := struct {
// comment
a: int,
b: int,
}

View file

@ -5,7 +5,9 @@ use {
instrs::{self, *},
lexer::TokenKind,
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,
Types,
},
@ -719,10 +721,11 @@ impl Codegen {
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
.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();
self.tys.structs.push(Struct { fields });
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.expect_advance(T::LBrace);
self.collect_list(T::Comma, T::RBrace, |s| {
let tok = s.token;
if s.advance_if(T::Comment) {
CommentOr::Comment { literal: s.move_str(tok), pos: tok.start }
} else {
let name = s.expect_advance(T::Ident);
s.expect_advance(T::Colon);
(s.move_str(name), s.expr())
CommentOr::Or(StructField {
pos: name.start,
name: s.move_str(name),
ty: s.expr(),
})
}
})
},
captured: {
@ -350,6 +359,7 @@ impl<'a, 'b> Parser<'a, 'b> {
s.declare(name.start, id, None);
s.expect_advance(T::Colon);
Arg {
pos: name.start,
name: s.move_str(name),
is_ct: name.kind == T::CtIdent,
id,
@ -578,6 +588,7 @@ pub fn find_symbol(symbols: &[Symbol], id: Ident) -> &Symbol {
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct Arg<'a> {
pub pos: u32,
pub name: &'a str,
pub id: Ident,
pub is_ct: bool,
@ -585,6 +596,12 @@ pub struct Arg<'a> {
pub ty: Expr<'a>,
}
impl Poser for Arg<'_> {
fn posi(&self) -> Pos {
self.pos
}
}
macro_rules! generate_expr {
($(#[$meta:meta])* $vis:vis enum $name:ident<$lt:lifetime> {$(
$(#[$field_meta:meta])*
@ -732,7 +749,7 @@ generate_expr! {
/// `'struct' LIST('{', ',', '}', Ident ':' Expr)`
Struct {
pos: Pos,
fields: &'a [(&'a str, Self)],
fields: &'a [CommentOr<'a, StructField<'a>>],
captured: &'a [Ident],
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)]
pub struct CtorField<'a> {
pub pos: Pos,
@ -840,22 +870,52 @@ pub struct CtorField<'a> {
pub value: Expr<'a>,
}
impl Poser for CtorField<'_> {
fn posi(&self) -> Pos {
self.pos
}
}
trait Poser {
fn posi(self) -> Pos;
fn posi(&self) -> Pos;
}
impl Poser for Pos {
fn posi(self) -> Pos {
self
fn posi(&self) -> Pos {
*self
}
}
impl<'a> Poser for &Expr<'a> {
fn posi(self) -> Pos {
impl<'a> Poser for Expr<'a> {
fn posi(&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! {
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()) };
}
fn fmt_list<T>(
fn fmt_list<T: Poser>(
f: &mut fmt::Formatter,
trailing: bool,
end: &str,
sep: &str,
list: &[T],
fmt: impl Fn(&T, &mut fmt::Formatter) -> fmt::Result,
) -> fmt::Result {
if !trailing {
let first = &mut true;
for expr in list {
if !std::mem::take(first) {
write!(f, ", ")?;
fmt_list_low(f, trailing, end, sep, list, |v, f| {
fmt(v, f)?;
Ok(true)
})
}
fmt(expr, f)?;
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 {
if !trailing {
let mut first = true;
for expr in list {
if !std::mem::take(&mut first) {
write!(f, "{sep} ")?;
}
first = !fmt(expr, f)?;
}
return write!(f, "{end}");
}
@ -895,12 +970,28 @@ impl<'a> fmt::Display for Expr<'a> {
writeln!(f)?;
INDENT.with(|i| i.set(i.get() + 1));
let res = (|| {
for stmt in list {
for (i, stmt) in list.iter().enumerate() {
for _ in 0..INDENT.with(|i| i.get()) {
write!(f, "\t")?;
}
fmt(stmt, f)?;
writeln!(f, ",")?;
let add_sep = fmt(stmt, 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(())
})();
@ -937,8 +1028,6 @@ impl<'a> fmt::Display for Expr<'a> {
Consecutive => Expr::UnOp { .. },
}
let source: &str = unsafe { &*FMT_SOURCE.with(|s| s.get()) };
match *self {
Self::Ct { value, .. } => write!(f, "$: {}", value),
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::Directive { name, args, .. } => {
write!(f, "@{name}(")?;
fmt_list(f, false, ")", args, fmt::Display::fmt)
fmt_list(f, false, ")", ",", args, fmt::Display::fmt)
}
Self::Struct { fields, trailing_comma, .. } => {
write!(f, "struct {{")?;
fmt_list(f, trailing_comma, "}", fields, |(name, val), f| {
write!(f, "{name}: {val}",)
fmt_list_low(f, trailing_comma, "}", ",", fields, |field, f| {
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, .. } => {
@ -967,14 +1060,14 @@ impl<'a> fmt::Display for Expr<'a> {
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, .. } => {
if let Some(ty) = ty {
write!(f, "{}", Unary(ty))?;
}
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 {
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::Closure { ret, body, args, .. } => {
write!(f, "fn(")?;
fmt_list(f, false, "", args, |arg, f| {
fmt_list(f, false, "", ",", args, |arg, f| {
if arg.is_ct {
write!(f, "$")?;
}
@ -1005,7 +1098,7 @@ impl<'a> fmt::Display for Expr<'a> {
}
Self::Call { func, args, trailing_comma } => {
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: 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::Block { stmts, .. } => {
write!(f, "{{")?;
writeln!(f)?;
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
fmt_list(f, true, "}", "", stmts, fmt::Display::fmt)
}
Self::Number { value, radix, .. } => match radix {
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)?;
if let Some(mut prev) = source.get(..right.pos() as usize) {
prev = prev.trim_end();

View file

@ -8,7 +8,7 @@ use {
parser::{
self,
idfl::{self},
Expr, ExprRef, FileId, Pos,
CommentOr, Expr, ExprRef, FileId, Pos, StructField,
},
task, ty, Field, Func, Reloc, Sig, Struct, SymKey, TypedReloc, Types,
},
@ -1397,10 +1397,11 @@ impl Codegen {
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
.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();
self.tys.structs.push(Struct { fields });
self.tys.structs.len() as u32 - 1