Skip to content

Commit

Permalink
compiler: fix code generation for map lookup and default value handling
Browse files Browse the repository at this point in the history
  • Loading branch information
mertcandav committed Sep 8, 2024
1 parent ac3d275 commit e2d76d6
Show file tree
Hide file tree
Showing 2 changed files with 90 additions and 41 deletions.
33 changes: 31 additions & 2 deletions src/julec/obj/cxx/expr.jule
Original file line number Diff line number Diff line change
Expand Up @@ -983,17 +983,46 @@ impl exprCoder {
ret
}

self.possibleRefExpr(m.Expr.Model)
// Index access with safety measures.
match {
| m.Expr.Kind.Map() != nil:
const valueIdent = "__lookup_val"
const okIdent = "__lookup_ok"
mut _map := m.Expr.Kind.Map()
self.oc.write("({ ")
self.oc.tc.kind(self.oc.Buf, _map.Val)
self.oc.write(" ")
self.oc.write(valueIdent)
self.oc.write("; ")
self.oc.write(typeCoder.Bool)
self.oc.write(" ")
self.oc.write(okIdent)
self.oc.write("; ")
self.possibleRefExpr(m.Expr.Model)
self.oc.write(".lookup(")
self.possibleRefExpr(m.Index.Model)
self.oc.write(", &")
self.oc.write(valueIdent)
self.oc.write(", &")
self.oc.write(okIdent)
self.oc.write("); if (!")
self.oc.write(okIdent)
self.oc.write(") ")
self.oc.write(valueIdent)
self.oc.write(" = ")
self.initExpr(_map.Val)
self.oc.write("; ")
self.oc.write(valueIdent)
self.oc.write("; })")
| env::Production
| m.Expr.Kind.Ptr() != nil
| m.Expr.Kind.Map() != nil
| obj::IsExprComesFromBind(m.Expr):
self.possibleRefExpr(m.Expr.Model)
self.oc.write("[")
self.possibleRefExpr(m.Index.Model)
self.oc.write("]")
|:
self.possibleRefExpr(m.Expr.Model)
self.oc.write(".at(\"")
self.oc.locInfo(m.Token)
self.oc.write("\", ")
Expand Down
98 changes: 59 additions & 39 deletions src/julec/obj/cxx/scope.jule
Original file line number Diff line number Diff line change
Expand Up @@ -468,8 +468,27 @@ impl scopeCoder {
self.oc.write(p.Op)
}

fn assignLeft(mut &self, mut &model: sema::ExprModel) {
match type model {
| &IndexingExprModel:
mut iem := (&IndexingExprModel)(model)
_map := iem.Expr.Kind.Map()
if _map == nil {
break
}
// Map indexing used for assignment.
// Generate direct lookup unlike expression coder.
self.oc.ec.possibleRefExpr(iem.Expr.Model)
self.oc.write("[")
self.oc.ec.possibleRefExpr(iem.Index.Model)
self.oc.write("]")
ret
}
self.oc.ec.possibleRefExpr(model)
}

fn divByZeroAssign(mut &self, mut a: &Assign) {
self.oc.ec.possibleRefExpr(a.Left.Model)
self.assignLeft(a.Left.Model)
self.oc.write(" = ")
self.oc.ec.divByZeroBinary(a.Op, a.Left, a.Right)
}
Expand All @@ -483,7 +502,7 @@ impl scopeCoder {
}
identCoder.funcIns(self.oc.Buf, f)
self.oc.write("(&")
self.oc.ec.possibleRefExpr(l.Model)
self.assignLeft(l.Model)
self.oc.write(", ")
self.oc.ec.possibleRefExpr(r.Model)
self.oc.write(")")
Expand All @@ -505,14 +524,14 @@ impl scopeCoder {
ret
}

self.oc.ec.possibleRefExpr(a.Left.Model)
self.assignLeft(a.Left.Model)
self.oc.write(a.Op.Kind)
self.oc.ec.possibleRefExpr(a.Right.Model)
}

fn mapLookupAssign(mut &self, mut &a: &MultiAssign) {
mut iem := (&IndexingExprModel)(a.Right)
self.oc.ec.possibleRefExpr(iem.Expr.Model)
self.assignLeft(iem.Expr.Model)
self.oc.write(".lookup(")
self.oc.ec.possibleRefExpr(iem.Index.Model)
self.oc.write(", ")
Expand Down Expand Up @@ -571,7 +590,7 @@ impl scopeCoder {
continue
}
self.oc.indent()
self.oc.ec.possibleRefExpr(l.Model)
self.assignLeft(l.Model)
self.oc.write(" = ")
identCoder.toOut(self.oc.Buf, assignArgName, uintptr(i))
self.oc.write(";\n")
Expand All @@ -595,44 +614,45 @@ impl scopeCoder {

mut tup := f.Func.Result.Tup()
for (i, mut l) in a.Left {
if l != nil {
const r = assignResultName + "." + resultArgName
self.oc.indent()
self.oc.ec.possibleRefExpr(l.Model)
match {
| tup.Types[i].Equal(l.Kind):
self.oc.write(" = " + r)
self.oc.write(conv::Itoa(i))
| obj::IsAny(l.Kind):
self.oc.write(" = " + typeCoder.Any + "(" + r)
self.oc.write(conv::Itoa(i))
self.oc.write(", &" + anyTypeIdent)
self.oc.write(conv::Itoa(self.oc.pushAnyType(tup.Types[i])))
self.oc.write(")")
|:
// It should be trait.
if tup.Types[i].Trait() != nil { // Different traits, cast.
self.oc.write(" = ")
mut t1 := l.Kind.Trait()
mut t2 := tup.Types[i].Trait()
self.oc.write(r)
self.oc.write(conv::Itoa(i))
self.oc.write(".map(")
self.oc.pushAndWriteMaskMapper(t1, t2)
self.oc.write(")")
break
}
t := l.Kind.Trait()
self.oc.write(" = " + typeCoder.Trait + "(" + r)
if l == nil {
continue
}
const r = assignResultName + "." + resultArgName
self.oc.indent()
self.assignLeft(l.Model)
match {
| tup.Types[i].Equal(l.Kind):
self.oc.write(" = " + r)
self.oc.write(conv::Itoa(i))
| obj::IsAny(l.Kind):
self.oc.write(" = " + typeCoder.Any + "(" + r)
self.oc.write(conv::Itoa(i))
self.oc.write(", &" + anyTypeIdent)
self.oc.write(conv::Itoa(self.oc.pushAnyType(tup.Types[i])))
self.oc.write(")")
|:
// It should be trait.
if tup.Types[i].Trait() != nil { // Different traits, cast.
self.oc.write(" = ")
mut t1 := l.Kind.Trait()
mut t2 := tup.Types[i].Trait()
self.oc.write(r)
self.oc.write(conv::Itoa(i))
self.oc.write(", (" + typeCoder.Trait + "::Type*)&")
identCoder.traitDecl(self.oc.Buf, t)
self.oc.write("_mptr_data")
self.oc.write(conv::Itoa(obj::FindTraitTypeOffset(t, tup.Types[i])))
self.oc.write(".map(")
self.oc.pushAndWriteMaskMapper(t1, t2)
self.oc.write(")")
break
}
self.oc.write(";\n")
t := l.Kind.Trait()
self.oc.write(" = " + typeCoder.Trait + "(" + r)
self.oc.write(conv::Itoa(i))
self.oc.write(", (" + typeCoder.Trait + "::Type*)&")
identCoder.traitDecl(self.oc.Buf, t)
self.oc.write("_mptr_data")
self.oc.write(conv::Itoa(obj::FindTraitTypeOffset(t, tup.Types[i])))
self.oc.write(")")
}
self.oc.write(";\n")
}

self.oc.doneIndent()
Expand Down

0 comments on commit e2d76d6

Please sign in to comment.