123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147 |
- package text_template
- import "core:fmt"
- import "core:reflect"
- import "core:strconv"
- Function :: #type proc(args: []any) -> (value: any, err: Error)
- @(private)
- new_any :: proc(x: $T) -> any {
- ptr := new_clone(x)
- return any{ptr, typeid_of(T)}
- }
- builtin_funcs: map[string]Function
- @(private, init)
- init_builtin_funcs :: proc() {
- builtin_funcs["and"] = nil // requires shortcircuiting behaviour so implemented internally
- builtin_funcs["or"] = nil // requires shortcircuiting behaviour so implemented internally
- builtin_funcs["not"] = proc(args: []any) -> (value: any, err: Error) {
- if len(args) != 1 {
- err = .Invalid_Argument_Count
- return
- }
- t, _ := is_true(args[0])
- return new_any(t), nil
- }
- builtin_funcs["index"] = proc(args: []any) -> (value: any, err: Error) {
- if len(args) < 2 {
- err = .Invalid_Argument_Count
- return
- }
- arg := args[0]
- for idx in args[1:] {
- i, ok := reflect.as_int(idx)
- if !ok {
- err = .Invalid_Argument_Type
- return
- }
- if reflect.length(arg) < i {
- return nil, .Out_Of_Bounds_Access
- }
- arg = reflect.index(arg, i)
- }
- return arg, nil
- }
- builtin_funcs["len"] = proc(args: []any) -> (value: any, err: Error) {
- if len(args) != 1 {
- err = .Invalid_Argument_Count
- return
- }
- n := reflect.length(args[0])
- return new_any(n), nil
- }
- builtin_funcs["int"] = proc(args: []any) -> (value: any, err: Error) {
- if len(args) != 1 {
- err = .Invalid_Argument_Count
- return
- }
- res: i64
- switch v in get_value(args[0]) {
- case bool:
- res = i64(v)
- case i64:
- res = i64(v)
- case f64:
- res = i64(v)
- case string:
- if value, ok := strconv.parse_f64(v); ok {
- res = i64(value)
- } else if value, ok := strconv.parse_i64(v); ok {
- res = i64(value)
- } else {
- return nil, .Invalid_Argument_Type
- }
- case:
- return nil, .Invalid_Argument_Type
- }
- return new_any(res), nil
- }
- builtin_funcs["float"] = proc(args: []any) -> (value: any, err: Error) {
- if len(args) != 1 {
- err = .Invalid_Argument_Count
- return
- }
- res: f64
- switch v in get_value(args[0]) {
- case bool:
- res = f64(i64(v))
- case i64:
- res = f64(v)
- case f64:
- res = f64(v)
- case string:
- if value, ok := strconv.parse_f64(v); ok {
- res = f64(value)
- } else if value, ok := strconv.parse_i64(v); ok {
- res = f64(value)
- } else {
- return nil, .Invalid_Argument_Type
- }
- case:
- return nil, .Invalid_Argument_Type
- }
- return new_any(res), nil
- }
- builtin_funcs["print"] = proc(args: []any) -> (value: any, err: Error) {
- return new_any(fmt.aprint(..args)), nil
- }
- builtin_funcs["println"] = proc(args: []any) -> (value: any, err: Error) {
- return new_any(fmt.aprintln(..args)), nil
- }
- builtin_funcs["printf"] = proc(args: []any) -> (value: any, err: Error) {
- if len(args) < 1 {
- err = .Invalid_Argument_Count
- return
- }
- format_any := args[0]
- format_any.id = reflect.typeid_base(format_any.id)
- format: string
- switch v in format_any {
- case string:
- format = v
- case cstring:
- format = string(v)
- case:
- err = .Invalid_Argument_Type
- return
- }
- other_args := args[1:]
- return new_any(fmt.aprintf(format, ..other_args)), nil
- }
- }
|