adding case checking

This commit is contained in:
Jakub Doka 2024-11-17 20:04:53 +01:00
parent fe5a8631f6
commit 95e9270fef
No known key found for this signature in database
GPG key ID: C6E9A89936B8C143
10 changed files with 112 additions and 50 deletions

File diff suppressed because one or more lines are too long

View file

@ -548,6 +548,10 @@ pub mod ty {
};)* };)*
} }
impl Builtin {
$(pub const $name: Self = Builtin($name);)*
}
impl Id { impl Id {
$(pub const $name: Self = Kind::Builtin(Builtin($name)).compress();)* $(pub const $name: Self = Kind::Builtin(Builtin($name)).compress();)*
} }
@ -755,7 +759,8 @@ pub mod ty {
TK::Global(idx) => { TK::Global(idx) => {
let global = &self.tys.ins.globals[idx]; let global = &self.tys.ins.globals[idx];
let file = &self.files[global.file.index()]; let file = &self.files[global.file.index()];
f.write_str(file.ident_str(global.name)) f.write_str(file.ident_str(global.name))?;
f.write_str(" (global)")
} }
TK::Slice(idx) => { TK::Slice(idx) => {
let array = self.tys.ins.slices[idx]; let array = self.tys.ins.slices[idx];
@ -770,7 +775,8 @@ pub mod ty {
TK::Const(idx) => { TK::Const(idx) => {
let cnst = &self.tys.ins.consts[idx]; let cnst = &self.tys.ins.consts[idx];
let file = &self.files[cnst.file.index()]; let file = &self.files[cnst.file.index()];
f.write_str(file.ident_str(cnst.name)) f.write_str(file.ident_str(cnst.name))?;
f.write_str(" (const)")
} }
} }
} }
@ -806,6 +812,7 @@ struct Func {
expr: ExprRef, expr: ExprRef,
sig: Option<Sig>, sig: Option<Sig>,
is_inline: bool, is_inline: bool,
returns_type: bool,
comp_state: [CompState; 2], comp_state: [CompState; 2],
} }
@ -1029,12 +1036,13 @@ pub struct Types {
trait TypeParser { trait TypeParser {
fn tys(&mut self) -> &mut Types; fn tys(&mut self) -> &mut Types;
fn ty_display(&self, of: ty::Id) -> ty::Display;
fn on_reuse(&mut self, existing: ty::Id); fn on_reuse(&mut self, existing: ty::Id);
fn find_local_ty(&mut self, name: Ident) -> Option<ty::Id>; fn find_local_ty(&mut self, name: Ident) -> Option<ty::Id>;
fn eval_const(&mut self, file: Module, expr: &Expr, ty: ty::Id) -> u64; fn eval_const(&mut self, file: Module, expr: &Expr, ty: ty::Id) -> u64;
fn eval_global(&mut self, file: Module, name: Ident, expr: &Expr) -> ty::Id; fn eval_global(&mut self, file: Module, name: Ident, expr: &Expr) -> ty::Id;
fn infer_type(&mut self, expr: &Expr) -> ty::Id; fn infer_type(&mut self, expr: &Expr) -> ty::Id;
fn report(&self, file: Module, pos: Pos, msg: impl Display) -> ty::Id; fn error(&self, file: Module, pos: Pos, msg: impl Display) -> ty::Id;
fn find_type( fn find_type(
&mut self, &mut self,
@ -1061,9 +1069,9 @@ trait TypeParser {
return match id { return match id {
Ok(_) => { Ok(_) => {
debug_assert_eq!(from_file, file); debug_assert_eq!(from_file, file);
self.report(file, pos, "somehow this was not found") self.error(file, pos, "somehow this was not found")
} }
Err("main") => self.report( Err("main") => self.error(
from_file, from_file,
pos, pos,
format_args!( format_args!(
@ -1074,13 +1082,13 @@ trait TypeParser {
), ),
), ),
Err(name) => { Err(name) => {
self.report(from_file, pos, format_args!("undefined indentifier: {name}")) self.error(from_file, pos, format_args!("undefined indentifier: {name}"))
} }
}; };
}; };
let tys = self.tys(); let tys = self.tys();
if let Some(&ty) = tys.syms.get(SymKey::Decl(file, name), &tys.ins) { let ty = if let Some(&ty) = tys.syms.get(SymKey::Decl(file, name), &tys.ins) {
ty ty
} else { } else {
let (is_ct, ty) = left let (is_ct, ty) = left
@ -1107,7 +1115,22 @@ trait TypeParser {
} }
tys.syms.insert(SymKey::Decl(file, name), ty, &tys.ins); tys.syms.insert(SymKey::Decl(file, name), ty, &tys.ins);
ty ty
};
if let Err(proper_case) = self.tys().case(ty)(f.ident_str(name)) {
self.error(
from_file,
pos,
format_args!(
"the declaration does not have conventional \
casing, expected '{proper_case}', \
because the declared type is '{}'",
self.ty_display(ty),
),
);
} }
ty
}; };
let tys = self.tys(); let tys = self.tys();
@ -1250,13 +1273,14 @@ trait TypeParser {
} }
let Some(args) = self.tys().pack_args(arg_base) else { let Some(args) = self.tys().pack_args(arg_base) else {
return self.report(file, pos, "function has too many argumnets"); return self.error(file, pos, "function has too many argumnets");
}; };
let ret = self.parse_ty(file, ret, None, files); let ret = self.parse_ty(file, ret, None, files);
Some(Sig { args, ret }) Some(Sig { args, ret })
}, },
expr: ExprRef::new(expr), expr: ExprRef::new(expr),
returns_type: matches!(ret, &Expr::Ident { id, .. } if ty::Builtin::try_from(id) == Ok(ty::Builtin::TYPE)),
..Default::default() ..Default::default()
}; };
@ -1269,6 +1293,21 @@ trait TypeParser {
} }
impl Types { impl Types {
pub fn case(&self, ty: ty::Id) -> fn(&str) -> Result<(), &'static str> {
match ty.expand() {
ty::Kind::NEVER => |_| Ok(()),
ty::Kind::Enum(_)
| ty::Kind::Struct(_)
| ty::Kind::Builtin(_)
| ty::Kind::Ptr(_)
| ty::Kind::Slice(_)
| ty::Kind::Opt(_) => utils::is_pascal_case,
ty::Kind::Func(f) if self.ins.funcs[f].returns_type => utils::is_pascal_case,
ty::Kind::Func(_) | ty::Kind::Global(_) | ty::Kind::Module(_) => utils::is_snake_case,
ty::Kind::Const(_) => utils::is_screaming_case,
}
}
fn pack_args(&mut self, arg_base: usize) -> Option<ty::Tuple> { fn pack_args(&mut self, arg_base: usize) -> Option<ty::Tuple> {
let base = self.ins.args.len(); let base = self.ins.args.len();
self.ins.args.extend(self.tmp.args.drain(arg_base..)); self.ins.args.extend(self.tmp.args.drain(arg_base..));

View file

@ -3597,7 +3597,7 @@ impl<'a> Codegen<'a> {
ret = ret.and(self.expr(stmt)); ret = ret.and(self.expr(stmt));
if let Some(mut id) = ret { if let Some(mut id) = ret {
if id.ty != ty::Id::VOID { if id.ty != ty::Id::VOID {
self.error( self.warn(
stmt.pos(), stmt.pos(),
fa!( fa!(
"statements need to evaluate to 'void', \ "statements need to evaluate to 'void', \
@ -4967,11 +4967,11 @@ impl<'a> Codegen<'a> {
value.ty = to; value.ty = to;
} }
//#[track_caller] #[track_caller]
//fn warn(&self, pos: Pos, msg: impl core::fmt::Display) { fn warn(&self, pos: Pos, msg: impl core::fmt::Display) {
// let mut buf = self.warnings.borrow_mut(); let mut buf = self.errors.borrow_mut();
// write!(buf, "{}", self.file().report(pos, msg)).unwrap(); write!(buf, "(W) {}", self.file().report(pos, msg)).unwrap();
//} }
#[track_caller] #[track_caller]
fn error(&self, pos: Pos, msg: impl core::fmt::Display) { fn error(&self, pos: Pos, msg: impl core::fmt::Display) {
@ -4995,6 +4995,10 @@ impl TypeParser for Codegen<'_> {
self.tys self.tys
} }
fn ty_display(&self, of: ty::Id) -> ty::Display {
self.ty_display(of)
}
fn eval_const(&mut self, file: Module, expr: &Expr, ret: ty::Id) -> u64 { fn eval_const(&mut self, file: Module, expr: &Expr, ret: ty::Id) -> u64 {
self.ct.activate(); self.ct.activate();
let mut scope = mem::take(&mut self.ci.scope.vars); let mut scope = mem::take(&mut self.ci.scope.vars);
@ -5062,7 +5066,7 @@ impl TypeParser for Codegen<'_> {
gid.into() gid.into()
} }
fn report(&self, file: Module, pos: Pos, msg: impl Display) -> ty::Id { fn error(&self, file: Module, pos: Pos, msg: impl Display) -> ty::Id {
let mut buf = self.errors.borrow_mut(); let mut buf = self.errors.borrow_mut();
write!(buf, "{}", self.files[file.index()].report(pos, msg)).unwrap(); write!(buf, "{}", self.files[file.index()].report(pos, msg)).unwrap();
ty::Id::NEVER ty::Id::NEVER

View file

@ -12,6 +12,25 @@ use {
}, },
}; };
fn decide(b: bool, name: &'static str) -> Result<(), &'static str> {
b.then_some(()).ok_or(name)
}
pub fn is_snake_case(str: &str) -> Result<(), &'static str> {
decide(str.bytes().all(|c| matches!(c, b'a'..=b'z' | b'0'..=b'9' | b'_')), "snake_case")
}
pub fn is_pascal_case(str: &str) -> Result<(), &'static str> {
decide(
str.as_bytes()[0].is_ascii_uppercase() && str.bytes().all(|c| c.is_ascii_alphanumeric()),
"PascalCase",
)
}
pub fn is_screaming_case(str: &str) -> Result<(), &'static str> {
decide(str.bytes().all(|c| matches!(c, b'A'..=b'Z' | b'0'..=b'9' | b'_')), "SCREAMING_CASE")
}
type Nid = u16; type Nid = u16;
pub union BitSet { pub union BitSet {

View file

@ -21,7 +21,7 @@ sin:
ANDI r15, r14, 255d ANDI r15, r14, 255d
ITF64 r16, r14 ITF64 r16, r14
MULI64 r15, r15, 4d MULI64 r15, r15, 4d
LRA r17, r0, :SIN_TABLE LRA r17, r0, :sin_table
LI32 r18, 1086918619w LI32 r18, 1086918619w
FC64T32 r16, r16, 1b FC64T32 r16, r16, 1b
ADDI64 r14, r14, 64d ADDI64 r14, r14, 64d

View file

@ -1,5 +1,5 @@
main: main:
LRA r13, r0, :SIN_TABLE LRA r13, r0, :sin_table
LD r13, r13, 80a, 8h LD r13, r13, 80a, 8h
CP r1, r13 CP r1, r13
JALA r0, r31, 0a JALA r0, r31, 0a

View file

@ -19,7 +19,7 @@ free:
CP r13, r2 CP r13, r2
CP r14, r3 CP r14, r3
CP r15, r4 CP r15, r4
LRA r16, r0, :FREE_SYS_CALL LRA r16, r0, :free_sys_call
LD r16, r16, 0a, 8h LD r16, r16, 0a, 8h
CP r2, r16 CP r2, r16
CP r3, r13 CP r3, r13
@ -49,7 +49,7 @@ main:
malloc: malloc:
CP r13, r2 CP r13, r2
CP r14, r3 CP r14, r3
LRA r15, r0, :MALLOC_SYS_CALL LRA r15, r0, :malloc_sys_call
LD r15, r15, 0a, 8h LD r15, r15, 0a, 8h
CP r2, r15 CP r2, r15
CP r3, r13 CP r3, r13

View file

@ -23,7 +23,7 @@ foo:
ST r33, r254, 40a, 8h ST r33, r254, 40a, 8h
LD r1, r32, 0a, 16h LD r1, r32, 0a, 16h
JMP :1 JMP :1
2: LRA r34, r0, :MAGIC 2: LRA r34, r0, :magic
LD r34, r34, 0a, 8h LD r34, r34, 0a, 8h
JNE r34, r32, :3 JNE r34, r32, :3
ADDI64 r32, r254, 16d ADDI64 r32, r254, 16d
@ -41,7 +41,7 @@ get:
ADDI64 r254, r254, -32d ADDI64 r254, r254, -32d
CP r13, r3 CP r13, r3
LD r13, r13, 0a, 1h LD r13, r13, 0a, 1h
LRA r14, r0, :MAGIC LRA r14, r0, :magic
ANDI r13, r13, 255d ANDI r13, r13, 255d
LD r14, r14, 0a, 8h LD r14, r14, 0a, 8h
JNE r14, r13, :0 JNE r14, r13, :0

View file

@ -2,7 +2,7 @@ get_format:
ADDI64 r254, r254, -16d ADDI64 r254, r254, -16d
LI8 r13, 1b LI8 r13, 1b
ADDI64 r14, r254, 0d ADDI64 r14, r254, 0d
LRA r15, r0, :BMP LRA r15, r0, :bmp
ST r13, r254, 0a, 1h ST r13, r254, 0a, 1h
LD r13, r15, 0a, 8h LD r13, r15, 0a, 8h
ST r13, r254, 8a, 8h ST r13, r254, 8a, 8h

View file

@ -1,6 +1,6 @@
main: main:
ADDI64 r254, r254, -4d ADDI64 r254, r254, -4d
LRA r13, r0, :MAGENTA LRA r13, r0, :magenta
ADDI64 r14, r254, 0d ADDI64 r14, r254, 0d
BMC r13, r14, 4h BMC r13, r14, 4h
LD r13, r254, 2a, 1h LD r13, r254, 2a, 1h