@@ -3,15 +3,18 @@ package eval
33import (
44 "fmt"
55 "math"
6+ "strings"
67
78 "github.com/Victorystick/scrapscript/types"
89)
910
10- func bindBuiltIns (reg * types.Registry ) Variables {
11+ func bindBuiltIns (reg * types.Registry ) (types.TypeScope , Variables ) {
12+ var scope types.TypeScope
1113 var builtIns = make (Variables )
1214
1315 define := func (name string , typ types.TypeRef , val Func ) {
1416 builtIns [name ] = BuiltInFunc {name , typ , val }
17+ scope = scope .Bind (name , typ )
1518 }
1619
1720 // Built-in types
@@ -27,8 +30,16 @@ func bindBuiltIns(reg *types.Registry) Variables {
2730 aToB := reg .Func (a , b )
2831 aList := reg .List (a )
2932 bList := reg .List (b )
33+ textList := reg .List (types .TextRef )
3034
3135 // Lists
36+ define ("list/length" , reg .Func (aList , types .IntRef ), func (val Value ) (Value , error ) {
37+ ls , ok := val .(List )
38+ if ! ok {
39+ return nil , fmt .Errorf ("expected list, but got %T" , val )
40+ }
41+ return Int (len (ls .elements )), nil
42+ })
3243 define ("list/map" , reg .Func (aToB , reg .Func (aList , bList )), func (val Value ) (Value , error ) {
3344 fn := Callable (val )
3445 if fn == nil {
@@ -56,8 +67,8 @@ func bindBuiltIns(reg *types.Registry) Variables {
5667 },
5768 }, nil
5869 })
59- // TODO: type
60- define ("list/fold" , types . NeverRef , func (acc Value ) (Value , error ) {
70+ accum := reg . Func ( a , reg . Func ( b , a ))
71+ define ("list/fold" , reg . Func ( a , reg . Func ( accum , reg . Func ( bList , a ))) , func (acc Value ) (Value , error ) {
6172 source := "list/fold " + acc .String ()
6273 return ScriptFunc {
6374 source : source ,
@@ -96,6 +107,22 @@ func bindBuiltIns(reg *types.Registry) Variables {
96107 },
97108 }, nil
98109 })
110+ define ("list/repeat" , reg .Func (types .IntRef , reg .Func (a , aList )), func (val Value ) (Value , error ) {
111+ n , ok := val .(Int )
112+ if ! ok {
113+ return nil , fmt .Errorf ("expected int, but got %T" , val )
114+ }
115+ return ScriptFunc {
116+ source : "list/repeat " + val .String (),
117+ fn : func (val Value ) (v Value , err error ) {
118+ elems := make ([]Value , int (n ))
119+ for i := range elems {
120+ elems [i ] = val
121+ }
122+ return List {val .Type (), elems }, nil
123+ },
124+ }, nil
125+ })
99126
100127 // Text
101128 define ("text/length" , reg .Func (types .TextRef , types .IntRef ), func (val Value ) (Value , error ) {
@@ -105,6 +132,46 @@ func bindBuiltIns(reg *types.Registry) Variables {
105132 }
106133 return Int (len (text )), nil
107134 })
135+ define ("text/repeat" , reg .Func (types .IntRef , reg .Func (types .TextRef , types .TextRef )), func (val Value ) (Value , error ) {
136+ n , ok := val .(Int )
137+ if ! ok {
138+ return nil , fmt .Errorf ("expected int, but got %T" , val )
139+ }
140+ return ScriptFunc {
141+ source : "text/repeat " + val .String (),
142+ fn : func (val Value ) (v Value , err error ) {
143+ text , ok := val .(Text )
144+ if ! ok {
145+ return nil , fmt .Errorf ("expected text, but got %T" , val )
146+ }
147+ return Text (strings .Repeat (string (text ), int (n ))), nil
148+ },
149+ }, nil
150+ })
151+ define ("text/join" , reg .Func (types .TextRef , reg .Func (textList , types .TextRef )), func (val Value ) (Value , error ) {
152+ sep , ok := val .(Text )
153+ if ! ok {
154+ return nil , fmt .Errorf ("expected text, but got %T" , val )
155+ }
156+ return ScriptFunc {
157+ source : "text/join " + val .String (),
158+ fn : func (val Value ) (v Value , err error ) {
159+ ls , ok := val .(List )
160+ if ! ok {
161+ return nil , fmt .Errorf ("expected list, but got %T" , val )
162+ }
163+ elems := make ([]string , len (ls .elements ))
164+ for i , v := range ls .elements {
165+ text , ok := v .(Text )
166+ if ! ok {
167+ return nil , fmt .Errorf ("expected text, but got %T" , v )
168+ }
169+ elems [i ] = string (text )
170+ }
171+ return Text (strings .Join (elems , string (sep ))), nil
172+ },
173+ }, nil
174+ })
108175
109176 // int -> float
110177 define ("to-float" , reg .Func (types .IntRef , types .FloatRef ), func (val Value ) (Value , error ) {
@@ -134,7 +201,7 @@ func bindBuiltIns(reg *types.Registry) Variables {
134201 return nil , fmt .Errorf ("cannot bytes/from-utf8-text on %T" , val )
135202 })
136203
137- return builtIns
204+ return scope , builtIns
138205}
139206
140207func roundFunc (round func (float64 ) float64 ) Func {
0 commit comments