diff --git a/std/comptime/type.jule b/std/comptime/type.jule index 3da3c1929..c716a770a 100644 --- a/std/comptime/type.jule +++ b/std/comptime/type.jule @@ -89,6 +89,10 @@ impl comptimeTypeInfo { // Supports only structure and enum types. fn Fields(self): comptimeStructFields | comptimeEnumFields + // Returns parameter information for function's parameters. + // Supports only function types. + fn Params(self): comptimeParams + // Returns comptime-type information datas for tuple types. // Supports only tuple types. fn Types(self): comptimeTypeInfos @@ -168,4 +172,26 @@ impl comptimeStructField { fn Name(self): str } +*/ + +/* >>> Hint comptimeParams implementation. + +// Private compile-time information wrapper for function parameters. +// Supports iterable implementations. +// Using with built-in len function returns count of fields as constant expression. +struct comptimeParams {} + +*/ + +/* >>> Hint comptimeParam implementation. + +// Private compile-time function parameter information wrapper. +struct comptimeParam {} + +impl comptimeParam { + // Returns name of parameter. + // Returns as constant expression. + fn Name(self): str +} + */ \ No newline at end of file diff --git a/std/jule/sema/builtin.jule b/std/jule/sema/builtin.jule index ae22d3830..b536dd757 100644 --- a/std/jule/sema/builtin.jule +++ b/std/jule/sema/builtin.jule @@ -638,6 +638,11 @@ fn builtinCallerLen(mut &e: &Eval, mut &fc: &FnCallExpr, mut &d: &Data): &Data { d.Constant = Const.NewI64(i64(len(dest.Kind.comptimeTypeInfos().types))) d.Model = d.Constant ret d + | dest.Kind.comptimeParams() != nil: + d.Kind = lenKind() + d.Constant = Const.NewI64(i64(len(dest.Kind.comptimeParams().params))) + d.Model = d.Constant + ret d |: e.pushErr(fc.Args[0].Token, LogMsg.InvalidExpr) ret nil @@ -886,6 +891,14 @@ fn builtinCallerStdComptimeRange(mut &e: &Eval, mut &fc: &FnCallExpr, mut &_: &D }, }, } + | d.Kind.comptimeParams() != nil: + ret &Data{ + Kind: &TypeKind{ + Kind: &comptimeRange{ + kind: d.Kind.comptimeParams(), + }, + }, + } |: 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 4f143fddc..2b0c7a2ed 100644 --- a/std/jule/sema/comptime.jule +++ b/std/jule/sema/comptime.jule @@ -236,6 +236,101 @@ impl comptimeRangeKind for comptimeEnumFields { } } +// Compile-time parameter for functions. +struct comptimeParam { + param: &ParamIns +} + +impl Kind for comptimeParam { + fn Str(self): str { ret "comptimeParam" } + fn Equal(&self, other: &TypeKind): bool { ret false } +} + +impl comptimeParam { + fn _Name(&self): &Data { + let mut constant = Const.NewStr(self.param.Decl.Ident) + ret &Data{ + Kind: &TypeKind{ + Kind: buildPrimType(PrimKind.Str), + }, + Constant: constant, + Model: constant, + } + } + + fn _Type(mut &self, mut &e: &Eval): &Data { + ret buildComptimeTypeInfoData(e.s, self.param.Kind) + } + + 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 parameters range for function. +struct comptimeParams { + params: []&ParamIns +} + +impl Kind for comptimeParams { + fn Str(self): str { ret "comptimeParams" } + fn Equal(&self, other: &TypeKind): bool { ret false } +} + +impl comptimeRangeKind for comptimeParams { + 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(comptimeParam), + }, + } + } + } + + 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.comptimeParam().param = self.params[i] + } + } + + fn len(self): int { + ret len(self.params) + } +} + // Compile-time type info range. struct comptimeTypeInfos { types: []&comptimeTypeInfo @@ -612,6 +707,19 @@ impl comptimeTypeInfo { ret buildComptimeTypeInfoData(e.s, f.Result) } + fn _Params(mut &self, mut &e: &Eval, mut &fc: &ast::FnCallExpr): &Data { + let mut f = self.base.Fn() + if f == nil { + e.pushErr(fc.Token, LogMsg.InvalidTypeForFn, self.base.Str(), "Result") + ret nil + } + ret &Data{ + Kind: &TypeKind{ + Kind: &comptimeParams{params: f.Params}, + } + } + } + fn subIdent(mut &self, ident: str): &Data { match ident { | "Str": @@ -663,6 +771,13 @@ impl comptimeTypeInfo { }, } ret buildAsComptimeMethodData(method) + | "Params": + let mut method = &FnIns{ + caller: fn(mut &e: &Eval, mut &fc: &ast::FnCallExpr, mut &_: &Data): &Data { + ret self._Params(e, fc) + }, + } + ret buildAsComptimeMethodData(method) | "Types": let mut method = &FnIns{ caller: fn(mut &e: &Eval, mut &fc: &ast::FnCallExpr, mut &_: &Data): &Data { diff --git a/std/jule/sema/eval.jule b/std/jule/sema/eval.jule index 74b9b8c17..8f81fc54f 100644 --- a/std/jule/sema/eval.jule +++ b/std/jule/sema/eval.jule @@ -2716,6 +2716,13 @@ impl Eval { self.pushErr(si.Ident, LogMsg.ObjHaveNotIdent, d.Kind.Str(), si.Ident.Kind) } ret cd + | d.Kind.comptimeParam() != nil: + let mut comptimeP = d.Kind.comptimeParam() + let mut cd = comptimeP.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 diff --git a/std/jule/sema/type.jule b/std/jule/sema/type.jule index f3e6172c0..030b07290 100644 --- a/std/jule/sema/type.jule +++ b/std/jule/sema/type.jule @@ -374,6 +374,8 @@ impl TypeKind { self.comptimeStructField() != nil || self.comptimeEnumFields() != nil || self.comptimeEnumField() != nil || + self.comptimeParams() != nil || + self.comptimeParam() != nil || self.comptimeRange() != nil } @@ -413,6 +415,24 @@ impl TypeKind { } } + fn comptimeParams(mut self): &comptimeParams { + match type self.Kind { + | &comptimeParams: + ret (&comptimeParams)(self.Kind) + |: + ret nil + } + } + + fn comptimeParam(mut self): &comptimeParam { + match type self.Kind { + | &comptimeParam: + ret (&comptimeParam)(self.Kind) + |: + ret nil + } + } + fn comptimeRange(mut self): &comptimeRange { match type self.Kind { | &comptimeRange: diff --git a/std/jule/sema/type2.jule b/std/jule/sema/type2.jule index 6c29d29f4..ff72bc0ba 100644 --- a/std/jule/sema/type2.jule +++ b/std/jule/sema/type2.jule @@ -1239,6 +1239,7 @@ impl rangeChecker { match type range.kind { | &comptimeStructFields | &comptimeEnumFields + | &comptimeParams | &comptimeTypeInfos: self.checkComptime() ret true