mirror of
https://github.com/Open-Argon/argon-v3.git
synced 2025-12-06 08:56:07 +00:00
148 lines
3.7 KiB
Go
148 lines
3.7 KiB
Go
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"strings"
|
|
)
|
|
|
|
var callCompile = makeRegex("( *)(.|\n)+\\((.|\n)*\\)( *)")
|
|
|
|
type call struct {
|
|
Callable any
|
|
Args []any
|
|
Code string
|
|
Line int
|
|
Path string
|
|
}
|
|
|
|
type Callable struct {
|
|
name string
|
|
params []string
|
|
run any
|
|
code string
|
|
stack stack
|
|
line int
|
|
}
|
|
|
|
func isCall(code UNPARSEcode) bool {
|
|
return callCompile.MatchString(code.code)
|
|
}
|
|
|
|
func parseCall(code UNPARSEcode, index int, codelines []UNPARSEcode) (any, bool, ArErr, int) {
|
|
trim := strings.TrimSpace(code.code)
|
|
trim = trim[:len(trim)-1]
|
|
splitby := strings.Split(trim, "(")
|
|
for i := 1; i < len(splitby); i++ {
|
|
name := strings.Join(splitby[0:i], "(")
|
|
argstr := strings.Join(splitby[i:], "(")
|
|
args, success, argserr := getValuesFromLetter(argstr, ",", index, codelines, false)
|
|
if !success {
|
|
if i == len(splitby)-1 {
|
|
return nil, false, argserr, 1
|
|
}
|
|
continue
|
|
}
|
|
resp, worked, err, linecount := translateVal(UNPARSEcode{code: name, realcode: code.realcode, line: index + 1, path: code.path}, index, codelines, 0)
|
|
if !worked {
|
|
if i == len(splitby)-1 {
|
|
return nil, false, err, 1
|
|
}
|
|
continue
|
|
}
|
|
return call{Callable: resp, Args: args, Line: code.line, Code: code.realcode, Path: code.path}, true, ArErr{}, linecount
|
|
}
|
|
return nil, false, ArErr{"Syntax Error", "invalid call", code.line, code.path, code.realcode, true}, 1
|
|
}
|
|
|
|
func runCall(c call, stack stack, stacklevel int) (any, ArErr) {
|
|
var callable any = c.Callable
|
|
switch x := c.Callable.(type) {
|
|
case builtinFunc:
|
|
callable = x
|
|
case Callable:
|
|
callable = x
|
|
default:
|
|
callable_, err := runVal(c.Callable, stack, stacklevel+1)
|
|
if err.EXISTS {
|
|
return nil, err
|
|
}
|
|
switch x := callable_.(type) {
|
|
case ArObject:
|
|
callable_, err := mapGet(ArMapGet{
|
|
x,
|
|
[]any{"__call__"},
|
|
true,
|
|
c.Line,
|
|
c.Code,
|
|
c.Path,
|
|
}, stack, stacklevel+1)
|
|
if !err.EXISTS {
|
|
callable = callable_
|
|
}
|
|
default:
|
|
callable = callable_
|
|
}
|
|
}
|
|
args := []any{}
|
|
level := append(stack, newscope())
|
|
for _, arg := range c.Args {
|
|
resp, err := runVal(arg, level, stacklevel+1)
|
|
if err.EXISTS {
|
|
return nil, err
|
|
}
|
|
args = append(args, resp)
|
|
}
|
|
switch x := callable.(type) {
|
|
case builtinFunc:
|
|
debugPrintln(x.name, args)
|
|
resp, err := x.FUNC(args...)
|
|
resp = AnyToArValid(resp)
|
|
if err.EXISTS {
|
|
if err.line == 0 {
|
|
err.line = c.Line
|
|
}
|
|
if err.path == "" {
|
|
err.path = c.Path
|
|
}
|
|
if err.code == "" {
|
|
err.code = c.Code
|
|
}
|
|
}
|
|
return resp, err
|
|
case Callable:
|
|
debugPrintln(x.name, args)
|
|
if len(x.params) != len(args) {
|
|
return nil, ArErr{"Runtime Error", "expected " + fmt.Sprint(len(x.params)) + " arguments, got " + fmt.Sprint(len(args)), c.Line, c.Path, c.Code, true}
|
|
}
|
|
l := anymap{}
|
|
for i, param := range x.params {
|
|
l[param] = args[i]
|
|
}
|
|
resp, err := runVal(x.run, append(x.stack, Map(l)), stacklevel+1)
|
|
return openReturn(resp), err
|
|
}
|
|
return nil, ArErr{"Runtime Error", "type '" + typeof(callable) + "' is not callable", c.Line, c.Path, c.Code, true}
|
|
}
|
|
|
|
func builtinCall(callable any, args []any) (any, ArErr) {
|
|
debugPrintln(callable, args)
|
|
|
|
switch x := callable.(type) {
|
|
case builtinFunc:
|
|
resp, err := x.FUNC(args...)
|
|
resp = AnyToArValid(resp)
|
|
return resp, err
|
|
case Callable:
|
|
if len(x.params) != len(args) {
|
|
return nil, ArErr{TYPE: "Runtime Error", message: "expected " + fmt.Sprint(len(x.params)) + " arguments, got " + fmt.Sprint(len(args)), EXISTS: true}
|
|
}
|
|
level := newscope()
|
|
for i, param := range x.params {
|
|
level.obj[param] = args[i]
|
|
}
|
|
resp, err := runVal(x.run, append(x.stack, level), 0)
|
|
return openReturn(resp), err
|
|
}
|
|
return nil, ArErr{TYPE: "Runtime Error", message: "type '" + typeof(callable) + "' is not callable", EXISTS: true}
|
|
}
|