Skip to content

Commit

Permalink
jule: add slice literal support for comptime range iterations
Browse files Browse the repository at this point in the history
  • Loading branch information
mertcandav committed Nov 30, 2024
1 parent 8e9f729 commit 1405677
Show file tree
Hide file tree
Showing 8 changed files with 112 additions and 29 deletions.
10 changes: 5 additions & 5 deletions src/julec/obj/cxx/expr.jule
Original file line number Diff line number Diff line change
Expand Up @@ -1043,7 +1043,7 @@ impl exprCoder {
self.oc.write("(*")
self.oc.write(collectionItIdent)
self.oc.write("++) = ")
self.possibleRefExpr(m.Elems[i])
self.possibleRefExpr(m.Elems[i].Model)
self.oc.write("; ")
}
self.oc.write(collectionIdent)
Expand Down Expand Up @@ -1238,7 +1238,7 @@ impl exprCoder {
if len(m.Elems) == 2 && m.Elems[1] == nil {
self.oc.tc.array(self.oc.Buf, m.Kind)
self.oc.write("(")
self.possibleRefExpr(m.Elems[0])
self.possibleRefExpr(m.Elems[0].Model)
self.oc.write(")")
ret
}
Expand All @@ -1262,7 +1262,7 @@ impl exprCoder {
self.oc.write("(*")
self.oc.write(collectionItIdent)
self.oc.write("++) = ")
self.possibleRefExpr(m.Elems[i])
self.possibleRefExpr(m.Elems[i].Model)
self.oc.write("; ")
}
if len(m.Elems) != m.Kind.N && ableToInit(m.Kind.Elem) {
Expand Down Expand Up @@ -1510,7 +1510,7 @@ impl exprCoder {
} else {
self.oc.write(destIdent + ".push(")
}
self.possibleRefExpr(m.Elems.Elems[0])
self.possibleRefExpr(m.Elems.Elems[0].Model)
self.oc.write("); }")
ret
}
Expand All @@ -1531,7 +1531,7 @@ impl exprCoder {
} else {
self.oc.write(".__push(")
}
self.possibleRefExpr(e)
self.possibleRefExpr(e.Model)
self.oc.write("); ")
}
self.oc.write("}")
Expand Down
16 changes: 14 additions & 2 deletions src/julec/obj/expr_inspector.jule
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,18 @@ impl ExprInspector {
}
}

fn args1(mut self, mut args: []&sema::Data) {
for i in args {
if args[i] == nil {
// We may have nil data with no error.
// For example, array expressions use nil data for filled mark.
continue
}
// Should be guaranteed that model points to the original memory.
self.inspect(unsafe { *(&args[i].Model) })
}
}

// Calls internal inspect step by expression model.
// It's unsafe because this expression is may not be in ordinary order.
// Internal configurations may change and unexpected behavior may occur.
Expand Down Expand Up @@ -67,10 +79,10 @@ impl ExprInspector {
self.args(fc.Args)
| &sema::SliceExpr:
mut s := (&sema::SliceExpr)(m)
self.args(s.Elems)
self.args1(s.Elems)
| &sema::ArrayExpr:
mut a := (&sema::ArrayExpr)(m)
self.args(a.Elems)
self.args1(a.Elems)
| &sema::IndexingExpr:
mut i := (&sema::IndexingExpr)(m)
self.inspect(i.Expr.Model)
Expand Down
4 changes: 2 additions & 2 deletions std/jule/sema/builtin.jule
Original file line number Diff line number Diff line change
Expand Up @@ -588,7 +588,7 @@ fn builtinCallerAppend(mut &e: &eval, mut &fc: &ast::FnCallExpr, mut &d: &Data):

mut slice := &SliceExpr{
ElemType: s.Elem,
Elems: make([]Expr, 0, len(fc.Args)-1),
Elems: make([]&Data, 0, len(fc.Args)-1),
}
for (_, mut arg) in fc.Args[1:] {
e1 = e.evalExpr(arg)
Expand All @@ -603,7 +603,7 @@ fn builtinCallerAppend(mut &e: &eval, mut &fc: &ast::FnCallExpr, mut &d: &Data):
// Helps to reduce error logs and duplicated logs.
_ = e.s.checkAssignType(reference, s.Elem, e1, arg.Token, e.getOwnerRefers())
}
slice.Elems = append(slice.Elems, e1.Model)
slice.Elems = append(slice.Elems, e1)
}
d.Model = &BuiltinAppendCallExpr{
Dest: t.Model,
Expand Down
45 changes: 45 additions & 0 deletions std/jule/sema/comptime.jule
Original file line number Diff line number Diff line change
Expand Up @@ -2092,6 +2092,51 @@ impl comptimeDecl {
}
}

struct comptimeSliceRange {
s: &SliceExpr
}

impl comptimeRangeKind for comptimeSliceRange {
fn ready(mut self, mut &keyA: &Var, mut &keyB: &Var) {
if keyA != nil {
keyA.Constant = true
keyA.Value = &Value{
Data: new(Data),
}
keyA.TypeSym = findBuiltinTypeAlias(types::Kind.Int).TypeSym
}
if keyB != nil {
keyB.Constant = true
keyB.Value = &Value{
Data: new(Data),
}
keyB.TypeSym = &TypeSym{
Type: self.s.ElemType,
}
}
}

fn index(mut self, mut &d: &Data, i: int) {
panic("sema: index method of comptimeSliceRange should not be used")
}

fn step(mut self, i: int, mut &keyA: &Var, mut &keyB: &Var) {
if keyA != nil {
// Kind should be assigned by caller.
keyA.Value.Data.Constant = constant::Const.NewI64(i64(i))
keyA.Value.Data.Model = keyA.Value.Data.Constant
}
if keyB != nil {
// Kind should be assigned by caller.
keyB.Value.Data = self.s.Elems[i]
}
}

fn len(self): int {
ret len(self.s.Elems)
}
}

fn buildAsComptimeMethodData(mut &f: &FnIns): &Data {
ret &Data{
Type: &Type{
Expand Down
32 changes: 19 additions & 13 deletions std/jule/sema/eval.jule
Original file line number Diff line number Diff line change
Expand Up @@ -838,9 +838,9 @@ impl eval {
Kind: arr,
}
if filled {
model.Elems = make([]Expr, 0, 2)
model.Elems = make([]&Data, 0, 2)
} else {
model.Elems = make([]Expr, 0, len(s.Exprs))
model.Elems = make([]&Data, 0, len(s.Exprs))
}

mut prefix := self.prefix
Expand All @@ -854,7 +854,7 @@ impl eval {
if self.s.checkValidityForInitExpr(self.target.mutable, destIsRef, arr.Elem, d, elem.Token) {
_ = self.s.checkAssignType(destIsRef, arr.Elem, d, elem.Token, self.getOwnerRefers())
}
model.Elems = append(model.Elems, d.Model)
model.Elems = append(model.Elems, d)
}
self.prefix = prefix

Expand All @@ -872,15 +872,15 @@ impl eval {
}
}

fn evalExpSlc(mut &self, mut s: &ast::SliceExpr, mut t: &Type, mut first: Expr): &Data {
fn evalExpSlc(mut &self, mut s: &ast::SliceExpr, mut t: &Type, mut first: &Data): &Data {
mut slc := &Slc{
Elem: t,
}

mut i := 0
mut model := &SliceExpr{
ElemType: t,
Elems: make([]Expr, 0, len(s.Exprs)),
Elems: make([]&Data, 0, len(s.Exprs)),
}
if first != nil {
model.Elems = append(model.Elems, first)
Expand All @@ -896,7 +896,7 @@ impl eval {
if self.s.checkValidityForInitExpr(self.target.mutable, destIsRef, slc.Elem, d, elem.Token) {
_ = self.s.checkAssignType(destIsRef, slc.Elem, d, elem.Token, self.getOwnerRefers())
}
model.Elems = append(model.Elems, d.Model)
model.Elems = append(model.Elems, d)
}
}
self.prefix = prefix
Expand Down Expand Up @@ -949,7 +949,7 @@ impl eval {
self.s.checkValidityForInitExpr(self.target.mutable, destIsRef,
firstElem.Type, firstElem, firstExpr.Token)

d = self.evalExpSlc(s, firstElem.Type, firstElem.Model)
d = self.evalExpSlc(s, firstElem.Type, firstElem)

self.prefix = prefix
ret d
Expand Down Expand Up @@ -1011,7 +1011,7 @@ impl eval {
if indx >= f64(len(m.Elems)) {
self.pushErr(i.Token, build::LogMsg.OverflowLimits)
} else {
d.Model = m.Elems[u64(indx)]
d.Model = m.Elems[u64(indx)].Model
d.Decl = true // Set Model: flag.
}
}
Expand Down Expand Up @@ -1578,7 +1578,7 @@ impl eval {
}

t = t.Slc().Elem
prim := t.Prim()
mut prim := t.Prim()
if prim == nil || (!prim.IsU8() && !prim.IsI32()) {
self.pushErr(errorToken, build::LogMsg.TypeNotSupportsCastingTo, d.Type.Str(), t.Str())
ret
Expand All @@ -1591,25 +1591,31 @@ impl eval {
s := c.ReadStr()
mut model := &SliceExpr{
ElemType: t,
Elems: make([]Expr, 0, len(s)),
Elems: make([]&Data, 0, len(s)),
}
for _, b in s {
mut bc := constant::Const.NewU64(u64(b))
bc.Kind = prim.Kind
model.Elems = append(model.Elems, bc)
model.Elems = append(model.Elems, &Data{
Type: &Type{Kind: prim},
Constant: bc,
})
}
d.Model = model
d.Decl = true // Prevent model changing.
| prim.IsI32():
runes := []rune(c.ReadStr())
mut model := &SliceExpr{
ElemType: t,
Elems: make([]Expr, 0, len(runes)),
Elems: make([]&Data, 0, len(runes)),
}
for _, r in runes {
mut rc := constant::Const.NewI64(i64(r))
rc.Kind = prim.Kind
model.Elems = append(model.Elems, rc)
model.Elems = append(model.Elems, &Data{
Type: &Type{Kind: prim},
Constant: rc,
})
}
d.Model = model
d.Decl = true // Prevent model changing.
Expand Down
4 changes: 2 additions & 2 deletions std/jule/sema/model.jule
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ struct FnCallExpr {
// For example: [1, 2, 3, 4, 5, 6, 8, 9, 10]
struct SliceExpr {
ElemType: &Type
Elems: []Expr
Elems: []&Data
}

// Indexing expression model.
Expand Down Expand Up @@ -191,7 +191,7 @@ struct StructStaticIdentExpr {
// First data is expression, second is nil, kind of mark to that array filled.
struct ArrayExpr {
Kind: &Arr
Elems: []Expr
Elems: []&Data
}

// Tuple expression model.
Expand Down
25 changes: 22 additions & 3 deletions std/jule/sema/scope.jule
Original file line number Diff line number Diff line change
Expand Up @@ -2115,22 +2115,41 @@ fn makeComptimeRange(mut &d: &Data) {
match {
| d.Type.comptimeStructFields() != nil:
d.Type = &Type{Kind: &comptimeRange{d.Type.comptimeStructFields()}}
ret
| d.Type.comptimeEnumFields() != nil:
d.Type = &Type{Kind: &comptimeRange{d.Type.comptimeEnumFields()}}
ret
| d.Type.comptimeTypeInfos() != nil:
d.Type = &Type{Kind: &comptimeRange{d.Type.comptimeTypeInfos()}}
ret
| d.Type.comptimeParams() != nil:
d.Type = &Type{Kind: &comptimeRange{d.Type.comptimeParams()}}
ret
| d.Type.comptimeStatics() != nil:
d.Type = &Type{Kind: &comptimeRange{d.Type.comptimeStatics()}}
ret
| d.Type.comptimeFiles() != nil:
d.Type = &Type{Kind: &comptimeRange{d.Type.comptimeFiles()}}
ret
| d.Type.comptimeDecls() != nil:
d.Type = &Type{Kind: &comptimeRange{d.Type.comptimeDecls()}}
|:
// Flag for failure.
d.Decl = true
ret
| d.Type.Slc() != nil:
match type d.Model {
| &SliceExpr:
mut s := (&SliceExpr)(d.Model)
for _, e in s.Elems {
if !e.IsConst() {
goto fail
}
}
d.Type = &Type{Kind: &comptimeRange{&comptimeSliceRange{s}}}
ret
}
}
fail:
// Flag for failure.
d.Decl = true
}

// Reports whether d can match at comptime.
Expand Down
5 changes: 3 additions & 2 deletions std/jule/sema/type2.jule
Original file line number Diff line number Diff line change
Expand Up @@ -865,7 +865,7 @@ impl fnCallArgChecker {
}

ok = ok && self.checkArg(p, d, arg.Token)
model.Elems = append(model.Elems, d.Model)
model.Elems = append(model.Elems, d)
}
self.e.prefix = old
self.e.target.mutable = oldMut
Expand Down Expand Up @@ -1262,7 +1262,8 @@ impl rangeChecker {
| &comptimeTypeInfos
| &comptimeStatics
| &comptimeFiles
| &comptimeDecls:
| &comptimeDecls
| &comptimeSliceRange:
self.checkComptime()
ret true
|:
Expand Down

0 comments on commit 1405677

Please sign in to comment.