Skip to content

Commit

Permalink
fix lvalue poof when calling method on rvalues
Browse files Browse the repository at this point in the history
  • Loading branch information
zhiayang committed Oct 11, 2019
1 parent 461e4ed commit 6a974fb
Show file tree
Hide file tree
Showing 6 changed files with 59 additions and 13 deletions.
38 changes: 32 additions & 6 deletions build/ultratiny.flx
Original file line number Diff line number Diff line change
Expand Up @@ -58,31 +58,57 @@ class Z: Y
class A
{
init() { }
virtual fn foo(a: Y) -> Y
virtual fn lol(a: Y) -> &Y
{
return Y(c: 471)
std::io::println("A::foo()")
return alloc Y(c: 471)
}
}

class B : A
{
init() : super() { }

override fn foo(a: Y) -> Y
override fn foo(a: Y) -> &Y
{
return Y(c: 748)
std::io::println("B::foo()")
return alloc Z(c: 748)
// return 3
}
}

// import std::io as _

// @entry fn main()
// {
// println("hello, world!")
// }

// issue #0: we basically don't really even check for overriding methods properly.
// issue #1: co/contra-variance of return and parameter types for virtual methods
// issue #2: crashes when initialisers have default arguments??

// classes are a Bad Idea (tm) ):

struct Tmp
{
k: int
m: int

fn meth() -> int => k * m
}

@entry fn main()
{
let a = B()
let q = a.foo(Y(c: 1)).data
// let a = B()
// let q = a.foo(Y(c: 1)).data

// let y: &X = alloc Y(c: 41)
// std::io::println("y = %", y.data)

// let q = Tmp(k: 3, m: 7).meth()

// let q = B().foo(Y(c: 1)).data
std::io::println("thing: %", q)
}

Expand Down
9 changes: 9 additions & 0 deletions source/codegen/dotop.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,15 @@ CGResult sst::MethodDotOp::_codegen(cgn::CodegenState* cs, fir::Type* infer)
fir::Type* sty = 0;
auto res = getAppropriateValuePointer(cs, this, this->lhs, &sty);

if(!res->islvalue())
{
auto tmplval = cs->irb.CreateLValue(this->lhs->type);
cs->irb.Store(res.value, tmplval);

res.value = tmplval;
res->makeConst();
}

// then we insert it as the first argument
auto rv = util::pool<sst::RawValueExpr>(this->loc, res.value->getType()->getMutablePointerTo());
rv->rawValue = CGResult(cs->irb.AddressOf(res.value, true));
Expand Down
6 changes: 6 additions & 0 deletions source/frontend/errors.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -467,6 +467,7 @@ void OverloadError::post()




[[noreturn]] void doTheExit(bool trace)
{
fprintf(stderr, "there were errors, compilation cannot continue\n");
Expand All @@ -487,3 +488,8 @@ void OverloadError::post()








8 changes: 7 additions & 1 deletion source/include/utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,13 @@ namespace util
template <typename T>
std::vector<T> take(const std::vector<T>& v, size_t num)
{
return std::vector<T>(v.begin(), v.begin() + num);
return std::vector<T>(v.begin(), v.begin() + std::min(num, v.size()));
}

template <typename T>
std::vector<T> drop(const std::vector<T>& v, size_t num)
{
return std::vector<T>(v.begin() + std::min(num, v.size()), v.end());
}

inline std::string join(const std::vector<std::string>& list, const std::string& sep)
Expand Down
8 changes: 3 additions & 5 deletions source/typecheck/classes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -209,13 +209,11 @@ TCResult ast::ClassDefn::typecheck(sst::TypecheckState* fs, fir::Type* infer, co
{
// ok -- issue is that we cannot compare the method signatures directly -- because the method will take the 'self' of its
// respective class, meaning they won't be duplicates. so, we must compare without the first parameter.

// note: we're passing by copy here intentionally so we can erase the first one.
auto compareMethods = [&fs](std::vector<FnParam> a, std::vector<FnParam> b) -> bool {
return fs->isDuplicateOverload(a, b);
auto compareMethodSignatures = [&fs](const std::vector<FnParam>& a, const std::vector<FnParam>& b) -> bool {
return fs->isDuplicateOverload(util::drop(a, 1), util::drop(b, 1));
};

if(bf->id.name == meth->id.name && compareMethods(bf->params, meth->params))
if(bf->id.name == meth->id.name && compareMethodSignatures(bf->params, meth->params))
{
// check for virtual functions.
//* note: we don't need to care if 'bf' is the base method, because if we are 'isOverride', then we are also
Expand Down
3 changes: 2 additions & 1 deletion source/typecheck/dotop.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -462,8 +462,9 @@ static sst::Expr* doExpressionDotOp(sst::TypecheckState* fs, ast::DotOperator* d

// ok.
auto defn = fs->typeDefnMap[type];
iceAssert(defn);

// note: if `defn` is null, then all the dcasts will fail and we'll
// fallthrough to the bottom.
if(auto str = dcast(sst::StructDefn, defn))
{
// right.
Expand Down

0 comments on commit 6a974fb

Please sign in to comment.