Skip to content

Commit

Permalink
Improve struct supertype coercion
Browse files Browse the repository at this point in the history
  • Loading branch information
aardappel committed Sep 16, 2023
1 parent d8c4d12 commit 2bca3bc
Show file tree
Hide file tree
Showing 8 changed files with 53 additions and 20 deletions.
12 changes: 12 additions & 0 deletions dev/src/lobster/codegen.h
Original file line number Diff line number Diff line change
Expand Up @@ -1231,6 +1231,18 @@ void ToInt::Generate(CodeGen &cg, size_t retval) const {
if (retval) cg.TakeTemp(1, false);
}

void ToStructSuper::Generate(CodeGen &cg, size_t retval) const {
// TODO: rather than chopping off extra fields, can see if child is an IdentRef and make it
// not push those fields in the first place.
cg.Gen(child, retval);
if (!retval) return;
cg.TakeTemp(1, true);
for (auto i = child->exptype->udt->sfields.size() - 1; i >= exptype->udt->sfields.size(); i--) {
auto &sfield = child->exptype->udt->sfields[i];
cg.GenPop({ sfield.type, lt });
}
}

void ToLifetime::Generate(CodeGen &cg, size_t retval) const {
cg.Gen(child, retval);
int stack_offset = 0;
Expand Down
4 changes: 4 additions & 0 deletions dev/src/lobster/constval.h
Original file line number Diff line number Diff line change
Expand Up @@ -433,4 +433,8 @@ ValueType ToLifetime::ConstVal(TypeChecker *, Value &) const {
return V_VOID;
}

ValueType ToStructSuper::ConstVal(TypeChecker *, Value &) const {
return V_VOID;
}

} // namespace lobster
1 change: 1 addition & 0 deletions dev/src/lobster/node.h
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,7 @@ COER_NODE(ToFloat, "tofloat", )
COER_NODE(ToString, "tostring", )
COER_NODE(ToBool, "tobool", )
COER_NODE(ToInt, "toint", )
COER_NODE(ToStructSuper, "tostructsuper", )
NARY_NODE(Block, "block", false, RETURNSMETHOD)
BINARY_NODE_T(IfThen, "if", false, Node, condition, Block, truepart, )
TERNARY_NODE_T(IfElse, "if", false, Node, condition, Block, truepart, Block, falsepart, RETURNSMETHOD)
Expand Down
35 changes: 26 additions & 9 deletions dev/src/lobster/typecheck.h
Original file line number Diff line number Diff line change
Expand Up @@ -295,14 +295,14 @@ struct TypeChecker {
return cf & CF_EXACTTYPE ? sd == 0 : sd >= 0;
}
case V_STRUCT_R:
case V_STRUCT_S:
return type->t == bound->t &&
(type->udt == bound->udt ||
// FIXME: total hack, allow passing subclass to superclass if same amount of fields.
// Need to also support multiple superclass steps.
// Need to also support extra fields if CF_COERCIONS.
(type->udt->ssuperclass == bound->udt &&
type->udt->ssuperclass->sfields.size() == bound->udt->sfields.size()));
case V_STRUCT_S: {
if (type->t != bound->t) return false;
if (SuperDistance(bound->udt, type->udt) < 0) return false;
// If number of fields is same as bound then this trivially converts.
if (type->udt->sfields.size() == bound->udt->sfields.size()) return true;
// This can convert if we chop off extra fields.
return (cf & CF_COERCIONS) != 0;
}
case V_TUPLE:
return type->t == V_TUPLE && ConvertsToTuple(*type->tup, *bound->tup);
case V_TYPEID:
Expand Down Expand Up @@ -389,6 +389,13 @@ struct TypeChecker {
n = tlt;
}

void MakeStructSuper(Node *&a, TypeRef structsuper) {
auto ss = new ToStructSuper(a->line, a);
ss->exptype = structsuper;
ss->lt = a->lt;
a = ss;
}

void StorageType(TypeRef type, const Node &context) {
if (type->HasValueType(V_VOID))
Error(context, "cannot store value of type ", Q(TypeName(type)));
Expand Down Expand Up @@ -475,7 +482,7 @@ struct TypeChecker {
extra = ConvertFlags(CF_COVARIANT | extra);
}
if (ConvertsTo(a->exptype, bound, ConvertFlags(CF_UNIFICATION | extra))) {
return;
return;
}
// Here follow the cases that needs explicit coercion code to be made compatible.
switch (bound->t) {
Expand All @@ -498,6 +505,16 @@ struct TypeChecker {
return;
}
break;
case V_STRUCT_R:
case V_STRUCT_S: {
if (a->exptype->t == bound->t &&
SuperDistance(bound->udt, a->exptype->udt) > 0 &&
a->exptype->udt->sfields.size() > bound->udt->sfields.size()) {
MakeStructSuper(a, bound);
return;
}
break;
}
default:
;
}
Expand Down
2 changes: 1 addition & 1 deletion modules/camera.lobster
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ class Camera:
// then still call FPS_view as before:
def direction(v):
v = normalize(v)
yaw = atan2(v.xy) - 90.0 // look along Y rather than X
yaw = atan2(v) - 90.0 // look along Y rather than X
pitch = asin(v.z)

// Default OpenGL view looks along -Z (Y up). This creates a worldspace where Z is up:
Expand Down
12 changes: 6 additions & 6 deletions modules/matrix.lobster
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,12 @@ import vec
struct mat2x2 : float4

def operator*(o:mat2x2):
return mat2x2 { dot(this.xy, o.xz), dot(this.xy, o.yw),
dot(this.zw, o.xz), dot(this.zw, o.yw) }
return mat2x2 { dot(o.xz, this), dot(o.yw, this),
dot(o.xz, this.zw), dot(o.yw, this.zw) }

def operator*(o:float2):
return float2 { dot(o, this.xy),
dot(o, this.zw) }
return float2 { dot(o, this),
dot(o, this.zw) }

def determinant():
return x*w - y*z
Expand All @@ -26,7 +26,7 @@ struct mat2x2 : float4
def trace():
return x*w


// The identity matrix:
// |1 0|
// |0 1|
Expand Down
3 changes: 1 addition & 2 deletions modules/quaternion.lobster
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,7 @@ struct quat : float4
return quat { -x, -y, -z, w }

def transform(p:float3):
let v = this.xyz
return p + cross(v, cross(v, p) + p * w) * 2.0
return p + cross(this, cross(this, p) + p * w) * 2.0

def quat_from_angle_axis(angle:float, axis:float3):
angle *= 0.5
Expand Down
4 changes: 2 additions & 2 deletions modules/vec.lobster
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,8 @@ let octant_directions = [
]

// shorten vectors, e.g. vec3 -> vec2
// FIXME: subtyping should take care of this
def xy(v): return vec2 { v.x, v.y }
def xy<T>(v:vec3<T>) -> vec2<T>: return v // Shorten by subtyping.
def xy<T>(v:vec4<T>) -> vec2<T>: return v // Shorten by subtyping.
def xz(v): return vec2 { v.x, v.z }
def yw(v): return vec2 { v.y, v.w }
def zw(v): return vec2 { v.z, v.w }
Expand Down

0 comments on commit 2bca3bc

Please sign in to comment.