import "libc.hff"; import "mem.hff"; import "option.hff"; /// Types struct Type; struct Decl; struct Expr; struct Env; struct Loc { fileid i16, col i16, line int, idx isize, } #[lax] enum TokT : i32 { // !sorted kw_and, kw_as, kw_break, kw_case, kw_const, kw_continue, kw_def, kw_defmacro, kw_do, kw_else, kw_enum, kw_extern, kw_fn, kw_for, kw_if, kw_import, kw_let, kw_or, kw_return, kw_sizeof, kw_static, kw_struct, kw_switch, kw_typedef, kw_typeof, kw_union, kw_while, NUM_KEYWORDS, int = -100, flo, bool, str, chr, null, ident, macident, gensym, type, label, strify, eof, } def NUM_KEYWORDS int = TokT:NUM_KEYWORDS; struct Tok { t TokT, loc Loc, ty *const Type, u union { int i64, uint u64, flo f64, bool bool, str [#]const u8, ident *const u8, }, } struct Type { size usize, align usize, konst bool, id uint, u enum union { Void, Bool, Int struct { sgn bool }, Flo, Ptr *Type, Arr struct { child *const Type, length i64 }, Slice *Type, Fn struct { params [#]*const Type, variadic bool, ret *const Type, }, }, fn is(ty *const Type, tag typeof((Type{}).u.#tag)) bool { return ty.u.#tag == tag; } } struct Parser { fp *FILE, alloc *Allocator, curfile *const u8, curenv *Env, tokloc Loc, curloc Loc, eof bool, peekchr Option, peektok Option, } enum UnOp { neg, not, compl, deref, addrof, postinc, preinc, postdec, predec, } struct Expr { loc Loc, ty *const Type, u enum union { IntLit union { i i64, u u64 }, FloLit f64, StrLit [#]const u8, BoolLit bool, NullLit, Symbol *Decl, BinOp struct { op TokT, lhs *Expr, rhs *Expr }, UnOp struct { op UnOp, ex *Expr }, Cond struct { test *Expr, t *Expr, f *Expr }, Call struct { lhs *Expr, args [#]Expr } } } struct Stmt { loc Loc, u enum union { Block [#]Stmt, Expr Expr, } } struct Fn { ty *const Type, paramnames [#]*const u8, variadic bool, id int, body Option<[#]Stmt> } struct Var { ty *const Type, ini Option, fnid int, } struct Decl { name *const u8, loc Loc, externp bool, u enum union { Let Var, Static Var, Fn Fn, Ty *const Type, }, } struct DeclList { link *DeclList, decl Decl, } struct Targ { name *const u8, ptrsize u8, intsize u8, i64align u8, longsize u8, longalign u8, llongsize u8, llongalign u8, sizesize u8, f64align u8, valistsize u8, valistalign u8, charsigned bool, shortenum bool, } // parse.cff extern static keyword2str [NUM_KEYWORDS]*const u8; extern fn parser_init(*Parser, path *const u8) void; extern fn parse(*Parser) [#]Decl; // fmt.cff extern fn vpfmt(proc *fn(u8, *void) void, parg *void, fmt *const u8, va_list) void; extern fn pfmt(proc *fn(u8, *void) void, parg *void, fmt *const u8, ...) void; extern fn vefmt(fmt *const u8, ap va_list) void; extern fn efmt(fmt *const u8, ...) void; extern fn ssfmt(fmt *const u8, ...) *const u8; extern fn err(P *Parser, Loc, fmt *const u8, ...) void; extern fn fatal(*Parser, Loc, fmt *const u8, ...) void; // targ.cff extern static g_targ *const Targ; extern fn targ_ini(name *const u8) bool; // type.cff extern static ty_void *const Type, ty_bool *const Type, ty_i8 *const Type, ty_u8 *const Type, ty_i16 *const Type, ty_u16 *const Type, ty_i32 *const Type, ty_u32 *const Type, ty_int *const Type, ty_uint *const Type, ty_i64 *const Type, ty_u64 *const Type, ty_isize *const Type, ty_usize *const Type, ty_iptrint *const Type, ty_uptrint *const Type, ty_f32 *const Type, ty_f64 *const Type, ty_voidptr *const Type; extern fn interntype(Type) *const Type; extern fn putprimtypes(env *Env) void; fn constify(ty *const Type) *const Type { if ty.konst or ty.u.#tag == :Fn { return ty; } let ty2 = *ty; ty2.konst = #t; return interntype(ty2); } fn unconstify(ty *const Type) *const Type { if !ty.konst { return ty; } let ty2 = *ty; ty2.konst = #f; return interntype(ty2); } fn mkarrtype(len i64, konst bool, child *const Type) *const Type { return interntype({ len * child.size, child.align, .u: :Arr { konst ? constify(child) : child, len } }); } fn mkptrtype(child *const Type) *const Type { return interntype({ g_targ.ptrsize, .u: :Ptr child }); } extern fn isnumtype(ty *const Type) bool; extern fn typeof2(a *const Type, b *const Type) *const Type; // env.cff extern fn mkenv(parent *Env, alloc *Allocator) *Env; extern fn envparent(*Env) *Env; extern fn envput(*Env, Decl, **const Decl) *Decl; extern fn envfind(*Env, *const u8) *Decl; extern fn envfree(*Env) void;