From 3197ab2dc395df777206b2b52a336ad02fe6cefc Mon Sep 17 00:00:00 2001 From: mertcandav Date: Thu, 27 Jun 2024 14:16:48 +0300 Subject: [PATCH] std::comptime: add tuple type support --- std/comptime/type.jule | 14 +++++++ std/jule/sema/builtin.jule | 13 ++++++ std/jule/sema/comptime.jule | 84 ++++++++++++++++++++++++++++++++++++- std/jule/sema/type.jule | 12 +++++- std/jule/sema/type2.jule | 3 +- 5 files changed, 123 insertions(+), 3 deletions(-) diff --git a/std/comptime/type.jule b/std/comptime/type.jule index 03131510c..4dc09faa0 100644 --- a/std/comptime/type.jule +++ b/std/comptime/type.jule @@ -31,6 +31,7 @@ enum Kind { UnsafePtr, // Unsafe raw pointer Ref, // Smart pointer Func, // Function + Tuple, // Tuple } // Returns compile-time type information. @@ -39,6 +40,15 @@ enum Kind { // will not executed at runtime. // fn TypeOf(TYPE || EXPRESSION): comptimeTypeInfo +/* >>> Hint comptimeTypeInfos implementation. + +// Private compile-time information wrapper for type infos. +// Supports iterable implementations. +// Using with built-in len function returns count of fields as constant expression. +struct comptimeTypeInfos {} + +*/ + /* >>> Hint comptimeTypeInfo implementation. // Private compile-time type information wrapper. @@ -79,6 +89,10 @@ impl comptimeTypeInfo { // Supports only structure and enum types. fn Fields(self): comptimeStructFields | comptimeEnumFields + // Returns comptime-type information datas for tuple types. + // Supports only tuple types. + fn Types(self): comptimeTypeInfos + // Reports whether type is public as constant expression. // Supports only structures, enums, type enums, and traits. fn Public(self): bool diff --git a/std/jule/sema/builtin.jule b/std/jule/sema/builtin.jule index 5b4a64b42..ae22d3830 100644 --- a/std/jule/sema/builtin.jule +++ b/std/jule/sema/builtin.jule @@ -633,6 +633,11 @@ fn builtinCallerLen(mut &e: &Eval, mut &fc: &FnCallExpr, mut &d: &Data): &Data { d.Constant = Const.NewI64(i64(len(dest.Kind.comptimeEnumFields().fields))) d.Model = d.Constant ret d + | dest.Kind.comptimeTypeInfos() != nil: + d.Kind = lenKind() + d.Constant = Const.NewI64(i64(len(dest.Kind.comptimeTypeInfos().types))) + d.Model = d.Constant + ret d |: e.pushErr(fc.Args[0].Token, LogMsg.InvalidExpr) ret nil @@ -873,6 +878,14 @@ fn builtinCallerStdComptimeRange(mut &e: &Eval, mut &fc: &FnCallExpr, mut &_: &D }, }, } + | d.Kind.comptimeTypeInfos() != nil: + ret &Data{ + Kind: &TypeKind{ + Kind: &comptimeRange{ + kind: d.Kind.comptimeTypeInfos(), + }, + }, + } |: e.pushErr(fc.Token, LogMsg.InvalidTypeForTypeOf, d.Kind.Str()) ret nil diff --git a/std/jule/sema/comptime.jule b/std/jule/sema/comptime.jule index af90cc326..0d0b108ac 100644 --- a/std/jule/sema/comptime.jule +++ b/std/jule/sema/comptime.jule @@ -236,6 +236,60 @@ impl comptimeRangeKind for comptimeEnumFields { } } +// Compile-time type info range. +struct comptimeTypeInfos { + types: []&comptimeType +} + +impl Kind for comptimeTypeInfos { + fn Str(self): str { ret "comptimeTypeInfos" } + fn Equal(&self, other: &TypeKind): bool { ret false } +} + +impl comptimeRangeKind for comptimeTypeInfos { + 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(comptimeType), + }, + } + } + } + + 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.Kind = self.types[i] + } + } + + fn len(self): int { + ret len(self.types) + } +} + // Compile-time type information data. struct comptimeType { base: &TypeKind @@ -286,6 +340,8 @@ impl comptimeType { item = enm.FindItem("Array") | self.base.Fn() != nil: item = enm.FindItem("Func") + | self.base.Tup() != nil: + item = enm.FindItem("Tuple") | self.base.Prim() != nil: let prim = self.base.Prim() match { @@ -508,6 +564,25 @@ impl comptimeType { } } + fn _Types(mut &self, mut &e: &Eval, mut &fc: &ast::FnCallExpr): &Data { + let mut tup = self.base.Tup() + if tup == nil { + e.pushErr(fc.Token, LogMsg.InvalidTypeForFn, self.base.Str(), "Types") + ret nil + } + let mut infos = &comptimeTypeInfos{ + types: make([]&comptimeType, 0, len(tup.Types)), + } + for (_, mut t) in tup.Types { + infos.types = append(infos.types, e.s.meta.pushComptimeType(t)) + } + ret &Data{ + Kind: &TypeKind{ + Kind: infos, + }, + } + } + fn subIdent(mut &self, ident: str): &Data { match ident { | "Str": @@ -559,6 +634,13 @@ impl comptimeType { }, } ret buildAsComptimeMethodData(method) + | "Types": + let mut method = &FnIns{ + caller: fn(mut &e: &Eval, mut &fc: &ast::FnCallExpr, mut &_: &Data): &Data { + ret self._Types(e, fc) + }, + } + ret buildAsComptimeMethodData(method) | "Public": let mut method = &FnIns{ caller: fn(mut &e: &Eval, mut &fc: &ast::FnCallExpr, mut &_: &Data): &Data { @@ -624,7 +706,7 @@ fn findComptimePackage(mut &s: &Sema): &ImportInfo { fn buildComptimeTypeInfoData(mut &s: &Sema, mut &t: &TypeKind): &Data { ret &Data{ Kind: &TypeKind{ - Kind: s.meta.pushComptimeType(t) + Kind: s.meta.pushComptimeType(t), }, } } \ No newline at end of file diff --git a/std/jule/sema/type.jule b/std/jule/sema/type.jule index 3940f8fa0..23f7be415 100644 --- a/std/jule/sema/type.jule +++ b/std/jule/sema/type.jule @@ -368,7 +368,8 @@ impl TypeKind { // Reports whether kind is comptime type. fn comptime(mut self): bool { - ret self.comptimeType() != nil || + ret self.comptimeTypeInfos() != nil || + self.comptimeType() != nil || self.comptimeStructFields() != nil || self.comptimeStructField() != nil || self.comptimeEnumFields() != nil || @@ -421,6 +422,15 @@ impl TypeKind { } } + fn comptimeTypeInfos(mut self): &comptimeTypeInfos { + match type self.Kind { + | &comptimeTypeInfos: + ret (&comptimeTypeInfos)(self.Kind) + |: + ret nil + } + } + fn comptimeType(mut self): &comptimeType { match type self.Kind { | &comptimeType: diff --git a/std/jule/sema/type2.jule b/std/jule/sema/type2.jule index 969b8b16e..6c29d29f4 100644 --- a/std/jule/sema/type2.jule +++ b/std/jule/sema/type2.jule @@ -1238,7 +1238,8 @@ impl rangeChecker { let mut range = self.d.Kind.comptimeRange() match type range.kind { | &comptimeStructFields - | &comptimeEnumFields: + | &comptimeEnumFields + | &comptimeTypeInfos: self.checkComptime() ret true |: