aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorlemon <lsof@mailbox.org>2022-08-25 11:26:13 +0200
committerlemon <lsof@mailbox.org>2022-08-25 11:26:13 +0200
commit90a57be9d1cf811ba26c09d6c8ac9f27067a5f85 (patch)
tree088b271b50d9d39e6cc2ef82c5726a401d486447 /src
parentf49ee40f689e86d7dc09bb9cc2d978b365a2df8b (diff)
slen, sptr, complete method type stuff
Diffstat (limited to 'src')
-rw-r--r--src/llvm.cff15
-rw-r--r--src/parse.cff34
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<Expr> = {};
+ 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, ')') {