Skip to content

Commit

Permalink
std::comptime: add enum type support to Fields method of comptimeType…
Browse files Browse the repository at this point in the history
…Info
  • Loading branch information
mertcandav committed Jun 26, 2024
1 parent 58a6325 commit 2ebf222
Show file tree
Hide file tree
Showing 6 changed files with 186 additions and 22 deletions.
40 changes: 31 additions & 9 deletions std/comptime/type.jule
Original file line number Diff line number Diff line change
Expand Up @@ -76,8 +76,8 @@ impl comptimeTypeInfo {
fn Value(self): comptimeTypeInfo

// Returns field informations for type.
// Supports only structure types.
fn Fields(self): comptimeFields
// Supports only structure and enum types.
fn Fields(self): comptimeStructFields | comptimeEnumFields

// Reports whether type is public as constant expression.
// Supports only structures, enums, type enums, and traits.
Expand All @@ -96,21 +96,21 @@ impl comptimeTypeInfo {

*/

/* >>> Hint comptimeFields implementation.
/* >>> Hint comptimeStructFields implementation.

// Private compile-time information wrapper for fields.
// Private compile-time information wrapper for struct fields.
// Supports iterable implementations.
// Using with built-in len function returns count of fields as constant expression.
struct comptimeFields {}
struct comptimeStructFields {}

*/

/* >>> Hint comptimeField implementation.
/* >>> Hint comptimeStructField implementation.

// Private compile-time field information wrapper.
struct comptimeField {}
// Private compile-time struct field information wrapper.
struct comptimeStructField {}

impl comptimeField {
impl comptimeStructField {
// Returns name of field.
// Returns as constant expression.
fn Name(self): str
Expand All @@ -122,4 +122,26 @@ impl comptimeField {
fn Type(self): comptimeTypeInfo
}

*/

/* >>> Hint comptimeEnumFields implementation.

// Private compile-time information wrapper for enum fields.
// Supports iterable implementations.
// Using with built-in len function returns count of fields as constant expression.
struct comptimeEnumFields {}

*/

/* >>> Hint comptimeEnumField implementation.

// Private compile-time enum field information wrapper.
struct comptimeEnumField {}

impl comptimeStructField {
// Returns name of field.
// Returns as constant expression.
fn Name(self): str
}

*/
13 changes: 13 additions & 0 deletions std/jule/sema/builtin.jule
Original file line number Diff line number Diff line change
Expand Up @@ -628,6 +628,11 @@ fn builtinCallerLen(mut &e: &Eval, mut &fc: &FnCallExpr, mut &d: &Data): &Data {
d.Constant = Const.NewI64(i64(len(dest.Kind.comptimeStructFields().fields)))
d.Model = d.Constant
ret d
| dest.Kind.comptimeEnumFields() != nil:
d.Kind = lenKind()
d.Constant = Const.NewI64(i64(len(dest.Kind.comptimeEnumFields().fields)))
d.Model = d.Constant
ret d
|:
e.pushErr(fc.Args[0].Token, LogMsg.InvalidExpr)
ret nil
Expand Down Expand Up @@ -860,6 +865,14 @@ fn builtinCallerStdComptimeRange(mut &e: &Eval, mut &fc: &FnCallExpr, mut &_: &D
},
},
}
| d.Kind.comptimeEnumFields() != nil:
ret &Data{
Kind: &TypeKind{
Kind: &comptimeRange{
kind: d.Kind.comptimeEnumFields(),
},
},
}
|:
e.pushErr(fc.Token, LogMsg.InvalidTypeForTypeOf, d.Kind.Str())
ret nil
Expand Down
121 changes: 111 additions & 10 deletions std/jule/sema/comptime.jule
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ struct comptimeStructField {
}

impl Kind for comptimeStructField {
fn Str(self): str { ret "comptimeField" }
fn Str(self): str { ret "comptimeStructField" }
fn Equal(&self, other: &TypeKind): bool { ret false }
}

Expand Down Expand Up @@ -145,6 +145,97 @@ impl comptimeRangeKind for comptimeStructFields {
}
}

// Compile-time field for enum.
struct comptimeEnumField {
field: &EnumItem
}

impl Kind for comptimeEnumField {
fn Str(self): str { ret "comptimeEnumField" }
fn Equal(&self, other: &TypeKind): bool { ret false }
}

impl comptimeEnumField {
fn _Name(&self): &Data {
let mut constant = Const.NewStr(self.field.Ident)
ret &Data{
Kind: &TypeKind{
Kind: buildPrimType(PrimKind.Str),
},
Constant: constant,
Model: constant,
}
}

fn subIdent(mut &self, ident: str): &Data {
match ident {
| "Name":
let mut method = &FnIns{
caller: fn(mut &e: &Eval, mut &fc: &ast::FnCallExpr, mut &_: &Data): &Data {
ret self._Name()
},
}
ret buildAsComptimeMethodData(method)
|:
ret nil
}
}
}

// Compile-time fields range for enum.
struct comptimeEnumFields {
fields: []&EnumItem
}

impl Kind for comptimeEnumFields {
fn Str(self): str { ret "comptimeEnumFields" }
fn Equal(&self, other: &TypeKind): bool { ret false }
}

impl comptimeRangeKind for comptimeEnumFields {
fn ready(mut self, mut &keyA: &Var, mut &keyB: &Var) {
if keyA != nil {
keyA.Constant = true
keyA.Value = &Value{
Data: new(Data),
}
keyA.Value.Data.Constant = nil
keyA.Kind = &TypeSymbol{
Kind: &TypeKind{
Kind: buildPrimType(PrimKind.Int),
},
}
}
if keyB != nil {
keyB.Constant = true
keyB.Value = &Value{
Data: new(Data),
}
keyB.Kind = &TypeSymbol{
Kind: &TypeKind{
Kind: new(comptimeEnumField),
},
}
}
}

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 = Const.NewI64(i64(i))
keyA.Value.Data.Model = keyA.Value.Data.Constant
}
if keyB != nil {
// Kind should be assigned by caller.
keyB.Kind.Kind.comptimeEnumField().field = self.fields[i]
}
}

fn len(self): int {
ret len(self.fields)
}
}

// Compile-time type information data.
struct comptimeType {
base: &TypeKind
Expand Down Expand Up @@ -325,17 +416,27 @@ impl comptimeType {

fn _Fields(mut &self, mut &e: &Eval, mut &fc: &ast::FnCallExpr): &Data {
let mut s = self.base.Struct()
if s == nil {
e.pushErr(fc.Token, LogMsg.InvalidTypeForFn, self.base.Str(), "Fields")
ret nil
if s != nil {
ret &Data{
Kind: &TypeKind{
Kind: &comptimeStructFields{
fields: s.Fields,
}
},
}
}
ret &Data{
Kind: &TypeKind{
Kind: &comptimeStructFields{
fields: s.Fields,
}
},
let mut enm = self.base.Enum()
if enm != nil {
ret &Data{
Kind: &TypeKind{
Kind: &comptimeEnumFields{
fields: enm.Items,
}
},
}
}
e.pushErr(fc.Token, LogMsg.InvalidTypeForFn, self.base.Str(), "Fields")
ret nil
}

fn _Public(mut &self, mut &e: &Eval, mut &fc: &ast::FnCallExpr): &Data {
Expand Down
7 changes: 7 additions & 0 deletions std/jule/sema/eval.jule
Original file line number Diff line number Diff line change
Expand Up @@ -2709,6 +2709,13 @@ impl Eval {
self.pushErr(si.Ident, LogMsg.ObjHaveNotIdent, d.Kind.Str(), si.Ident.Kind)
}
ret cd
| d.Kind.comptimeEnumField() != nil:
let mut comptimeEF = d.Kind.comptimeEnumField()
let mut cd = comptimeEF.subIdent(si.Ident.Kind)
if cd == nil {
self.pushErr(si.Ident, LogMsg.ObjHaveNotIdent, d.Kind.Str(), si.Ident.Kind)
}
ret cd
}

let mut kind = d.Kind
Expand Down
20 changes: 20 additions & 0 deletions std/jule/sema/type.jule
Original file line number Diff line number Diff line change
Expand Up @@ -371,6 +371,8 @@ impl TypeKind {
ret self.comptimeType() != nil ||
self.comptimeStructFields() != nil ||
self.comptimeStructField() != nil ||
self.comptimeEnumFields() != nil ||
self.comptimeEnumField() != nil ||
self.comptimeRange() != nil
}

Expand All @@ -392,6 +394,24 @@ impl TypeKind {
}
}

fn comptimeEnumFields(mut self): &comptimeEnumFields {
match type self.Kind {
| &comptimeEnumFields:
ret (&comptimeEnumFields)(self.Kind)
|:
ret nil
}
}

fn comptimeEnumField(mut self): &comptimeEnumField {
match type self.Kind {
| &comptimeEnumField:
ret (&comptimeEnumField)(self.Kind)
|:
ret nil
}
}

fn comptimeRange(mut self): &comptimeRange {
match type self.Kind {
| &comptimeRange:
Expand Down
7 changes: 4 additions & 3 deletions std/jule/sema/type2.jule
Original file line number Diff line number Diff line change
Expand Up @@ -1220,7 +1220,7 @@ impl rangeChecker {
}
}

fn checkComptimeStructFields(mut self, mut data: &comptimeStructFields) {
fn checkComptime(mut self) {
self.setSizeKey()
if self.rang.KeyA != nil && self.rang.KeyA.Mutable {
self.sc.s.pushErr(self.rang.KeyA.Token, LogMsg.CannotBeMut, self.rang.KeyA.Ident)
Expand All @@ -1237,8 +1237,9 @@ impl rangeChecker {
fn checkComptimeRange(mut self): bool {
let mut range = self.d.Kind.comptimeRange()
match type range.kind {
| &comptimeStructFields:
self.checkComptimeStructFields((&comptimeStructFields)(range.kind))
| &comptimeStructFields
| &comptimeEnumFields:
self.checkComptime()
ret true
|:
self.sc.s.pushErr(self.rang.InToken, LogMsg.IterRangeRequireEnumerableExpr)
Expand Down

0 comments on commit 2ebf222

Please sign in to comment.