From 90a57be9d1cf811ba26c09d6c8ac9f27067a5f85 Mon Sep 17 00:00:00 2001 From: lemon Date: Thu, 25 Aug 2022 11:26:13 +0200 Subject: slen, sptr, complete method type stuff --- src/llvm.cff | 15 +++++++++++++++ src/parse.cff | 34 +++++++++++++++++++++++++++++++--- 2 files changed, 46 insertions(+), 3 deletions(-) diff --git a/src/llvm.cff b/src/llvm.cff index a81bea4..ba4b556 100644 --- a/src/llvm.cff +++ b/src/llvm.cff @@ -281,6 +281,8 @@ fn genaddr(f *Fn, ex *Expr) Value { fn convert(f *Fn, to *const Type, ex *Expr) Value { to = unconstify(to); let from = unconstify(ex.ty); + if to->is(:Enum) { to = to.u.Enum.intty; } + if from->is(:Enum) { from = from.u.Enum.intty; } defmacro cvt(inst) [ (do let t = mktmp(to), @@ -366,6 +368,7 @@ fn convert(f *Fn, to *const Type, ex *Expr) Value { return genexpr(f, ex); case else + efmt("%t %t\n",from,to); assert(#f, "convert"); } } @@ -657,6 +660,18 @@ fn genexpr(f *Fn, ex *Expr) Value { gen("\t%v = load %t, %t %v\n", tmp, ex.ty, addr.ty, addr); return tmp; + case SPtr sl; + let sl = genexpr(f, sl); + let ptr = mktmp(mkptrtype(sl.ty.u.Slice)); + gen("\t%v = extractvalue %t %v, 0\n", ptr, sl.ty, sl); + return ptr; + + case SLen sl; + let sl = genexpr(f, sl); + let len = mktmp(ty_usize); + gen("\t%v = extractvalue %t %v, 1\n", len, sl.ty, sl); + return len; + case EUTag; let tmp = mktmp(ex.ty); let addr = genaddr(f, ex); diff --git a/src/parse.cff b/src/parse.cff index 85d9de5..0eb251d 100644 --- a/src/parse.cff +++ b/src/parse.cff @@ -756,7 +756,6 @@ fn parseagg(P *Parser, loc Loc, kind AggKind, name *const u8, retdecl **Decl) *c size = kind == :Struct ? off + type.size : MAX(size, type.size); } - efmt("%s\t %s\t off %z\n", agg.name ?? "?", name, off); flds->push({ name, type, off }); if !lexmatch(P, #null, ',') { @@ -1666,10 +1665,10 @@ fn pexpostfix(P *Parser) Expr { case lexmatch(P, &tok, '->'); let name = (tok = lexexpects(P, :ident, "method name")).u.ident; let ty = ex.ty; - if ty->is(:Ptr) { + let exptr = #f; + if (exptr = ty->is(:Ptr)) { ty = ty.u.Ptr; } - ty = unconstify(ty); if !ty->is(:Agg) { fatal(P, tok.loc, "left-hand-side is not an aggregate (%t)", ty); } @@ -1685,7 +1684,36 @@ fn pexpostfix(P *Parser) Expr { if Fn.params.#len == 0 { fatal(P, tok.loc, "function takes no arguments"); } + let args Vec = {}; + let recv0 = Fn.params[0], recv = recv0; + let metptr = #f; + if (metptr = recv->is(:Ptr)) { + recv = recv.u.Ptr; + } + if unconstify(ty) != unconstify(recv) { + err(P, tok.loc, "method receiver type mismatch for `->%s' (%t, expected %t)", + name, ty, recv0); + } + switch { + case !exptr and !metptr; + + case exptr and !metptr; + ex = { ex.loc, ty, :UnOp{:deref, exprdup(P.alloc, ex)}}; + + case !exptr and metptr; + if !islvalue(ex) { + err(P, tok.loc, "cannot call `->%s' by reference, lhs is not an lvalue", name); + } else if ty.konst and !recv.konst { + err(P, tok.loc, "constness mismatch: method takes %t but got %t", recv0, ex.ty); + } + ex = { ex.loc, mkptrtype(ty), :UnOp{:addrof, exprdup(P.alloc, ex)}}; + + case exptr and metptr; + if ty.konst and !recv.konst { + err(P, tok.loc, "constness mismatch: method takes %t but got %t", recv0, ex.ty); + } + } args->push(ex); let param = &Fn.params[1]; while !lexmatch(P, #null, ')') { -- cgit v1.2.3