mirror of
https://github.com/Open-Argon/argon-v3.git
synced 2025-12-06 00:46:07 +00:00
make arrays an object
This commit is contained in:
11
example.ar
11
example.ar
@@ -1,8 +1,5 @@
|
||||
i = 0
|
||||
output = []
|
||||
x = map()
|
||||
x.poo = 10
|
||||
|
||||
while (i < 1000) do
|
||||
output = append(output, i)
|
||||
i = i + 1
|
||||
|
||||
file.write('output.json').json(output)
|
||||
y = [x,x,x]
|
||||
term.log(y)
|
||||
68
output.json
68
output.json
@@ -1,68 +0,0 @@
|
||||
[
|
||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
|
||||
21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39,
|
||||
40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58,
|
||||
59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77,
|
||||
78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96,
|
||||
97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112,
|
||||
113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127,
|
||||
128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142,
|
||||
143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157,
|
||||
158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172,
|
||||
173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187,
|
||||
188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202,
|
||||
203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217,
|
||||
218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232,
|
||||
233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247,
|
||||
248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262,
|
||||
263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277,
|
||||
278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292,
|
||||
293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307,
|
||||
308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322,
|
||||
323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337,
|
||||
338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352,
|
||||
353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367,
|
||||
368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382,
|
||||
383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397,
|
||||
398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412,
|
||||
413, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427,
|
||||
428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, 442,
|
||||
443, 444, 445, 446, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 457,
|
||||
458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472,
|
||||
473, 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, 484, 485, 486, 487,
|
||||
488, 489, 490, 491, 492, 493, 494, 495, 496, 497, 498, 499, 500, 501, 502,
|
||||
503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517,
|
||||
518, 519, 520, 521, 522, 523, 524, 525, 526, 527, 528, 529, 530, 531, 532,
|
||||
533, 534, 535, 536, 537, 538, 539, 540, 541, 542, 543, 544, 545, 546, 547,
|
||||
548, 549, 550, 551, 552, 553, 554, 555, 556, 557, 558, 559, 560, 561, 562,
|
||||
563, 564, 565, 566, 567, 568, 569, 570, 571, 572, 573, 574, 575, 576, 577,
|
||||
578, 579, 580, 581, 582, 583, 584, 585, 586, 587, 588, 589, 590, 591, 592,
|
||||
593, 594, 595, 596, 597, 598, 599, 600, 601, 602, 603, 604, 605, 606, 607,
|
||||
608, 609, 610, 611, 612, 613, 614, 615, 616, 617, 618, 619, 620, 621, 622,
|
||||
623, 624, 625, 626, 627, 628, 629, 630, 631, 632, 633, 634, 635, 636, 637,
|
||||
638, 639, 640, 641, 642, 643, 644, 645, 646, 647, 648, 649, 650, 651, 652,
|
||||
653, 654, 655, 656, 657, 658, 659, 660, 661, 662, 663, 664, 665, 666, 667,
|
||||
668, 669, 670, 671, 672, 673, 674, 675, 676, 677, 678, 679, 680, 681, 682,
|
||||
683, 684, 685, 686, 687, 688, 689, 690, 691, 692, 693, 694, 695, 696, 697,
|
||||
698, 699, 700, 701, 702, 703, 704, 705, 706, 707, 708, 709, 710, 711, 712,
|
||||
713, 714, 715, 716, 717, 718, 719, 720, 721, 722, 723, 724, 725, 726, 727,
|
||||
728, 729, 730, 731, 732, 733, 734, 735, 736, 737, 738, 739, 740, 741, 742,
|
||||
743, 744, 745, 746, 747, 748, 749, 750, 751, 752, 753, 754, 755, 756, 757,
|
||||
758, 759, 760, 761, 762, 763, 764, 765, 766, 767, 768, 769, 770, 771, 772,
|
||||
773, 774, 775, 776, 777, 778, 779, 780, 781, 782, 783, 784, 785, 786, 787,
|
||||
788, 789, 790, 791, 792, 793, 794, 795, 796, 797, 798, 799, 800, 801, 802,
|
||||
803, 804, 805, 806, 807, 808, 809, 810, 811, 812, 813, 814, 815, 816, 817,
|
||||
818, 819, 820, 821, 822, 823, 824, 825, 826, 827, 828, 829, 830, 831, 832,
|
||||
833, 834, 835, 836, 837, 838, 839, 840, 841, 842, 843, 844, 845, 846, 847,
|
||||
848, 849, 850, 851, 852, 853, 854, 855, 856, 857, 858, 859, 860, 861, 862,
|
||||
863, 864, 865, 866, 867, 868, 869, 870, 871, 872, 873, 874, 875, 876, 877,
|
||||
878, 879, 880, 881, 882, 883, 884, 885, 886, 887, 888, 889, 890, 891, 892,
|
||||
893, 894, 895, 896, 897, 898, 899, 900, 901, 902, 903, 904, 905, 906, 907,
|
||||
908, 909, 910, 911, 912, 913, 914, 915, 916, 917, 918, 919, 920, 921, 922,
|
||||
923, 924, 925, 926, 927, 928, 929, 930, 931, 932, 933, 934, 935, 936, 937,
|
||||
938, 939, 940, 941, 942, 943, 944, 945, 946, 947, 948, 949, 950, 951, 952,
|
||||
953, 954, 955, 956, 957, 958, 959, 960, 961, 962, 963, 964, 965, 966, 967,
|
||||
968, 969, 970, 971, 972, 973, 974, 975, 976, 977, 978, 979, 980, 981, 982,
|
||||
983, 984, 985, 986, 987, 988, 989, 990, 991, 992, 993, 994, 995, 996, 997,
|
||||
998, 999
|
||||
]
|
||||
237
src/array.go
237
src/array.go
@@ -5,7 +5,7 @@ import "strings"
|
||||
var arrayCompile = makeRegex(`( *)\[(.|\n)*\]( *)`)
|
||||
|
||||
type CreateArray struct {
|
||||
value ArArray
|
||||
value []any
|
||||
line int
|
||||
code string
|
||||
path string
|
||||
@@ -15,6 +15,233 @@ func isArray(code UNPARSEcode) bool {
|
||||
return arrayCompile.MatchString(code.code)
|
||||
}
|
||||
|
||||
func ArArray(arr []any) ArObject {
|
||||
val := ArObject{
|
||||
"array",
|
||||
anymap{
|
||||
"__value__": arr,
|
||||
"length": len(arr),
|
||||
},
|
||||
}
|
||||
val.obj["remove"] = builtinFunc{
|
||||
"remove",
|
||||
func(args ...any) (any, ArErr) {
|
||||
if len(args) != 1 {
|
||||
return nil, ArErr{
|
||||
TYPE: "TypeError",
|
||||
message: "missing argument",
|
||||
EXISTS: true,
|
||||
}
|
||||
}
|
||||
if typeof(args[0]) != "number" {
|
||||
return nil, ArErr{
|
||||
TYPE: "TypeError",
|
||||
message: "argument must be a number",
|
||||
EXISTS: true,
|
||||
}
|
||||
}
|
||||
if !args[0].(number).IsInt() {
|
||||
return nil, ArErr{
|
||||
TYPE: "TypeError",
|
||||
message: "argument must be an integer",
|
||||
EXISTS: true,
|
||||
}
|
||||
}
|
||||
num := int(args[0].(number).Num().Int64())
|
||||
if num < 0 || num >= len(arr) {
|
||||
return nil, ArErr{
|
||||
TYPE: "IndexError",
|
||||
message: "index out of range",
|
||||
EXISTS: true,
|
||||
}
|
||||
}
|
||||
arr = append(arr[:num], arr[num+1:]...)
|
||||
val.obj["length"] = len(arr)
|
||||
val.obj["__value__"] = arr
|
||||
return nil, ArErr{}
|
||||
}}
|
||||
val.obj["append"] = builtinFunc{
|
||||
"append",
|
||||
func(args ...any) (any, ArErr) {
|
||||
if len(args) == 0 {
|
||||
return nil, ArErr{
|
||||
TYPE: "TypeError",
|
||||
message: "missing argument",
|
||||
EXISTS: true,
|
||||
}
|
||||
}
|
||||
arr = append(arr, args...)
|
||||
val.obj["length"] = len(arr)
|
||||
val.obj["__value__"] = arr
|
||||
return nil, ArErr{}
|
||||
},
|
||||
}
|
||||
val.obj["insert"] = builtinFunc{
|
||||
"insert",
|
||||
func(args ...any) (any, ArErr) {
|
||||
if len(args) < 2 {
|
||||
return nil, ArErr{
|
||||
TYPE: "TypeError",
|
||||
message: "missing argument",
|
||||
EXISTS: true,
|
||||
}
|
||||
}
|
||||
if typeof(args[0]) != "number" {
|
||||
return nil, ArErr{
|
||||
TYPE: "TypeError",
|
||||
message: "argument must be a number",
|
||||
EXISTS: true,
|
||||
}
|
||||
}
|
||||
if !args[0].(number).IsInt() {
|
||||
return nil, ArErr{
|
||||
TYPE: "TypeError",
|
||||
message: "argument must be an integer",
|
||||
EXISTS: true,
|
||||
}
|
||||
}
|
||||
num := int(args[0].(number).Num().Int64())
|
||||
if num < 0 || num > len(arr) {
|
||||
return nil, ArErr{
|
||||
TYPE: "IndexError",
|
||||
message: "index out of range",
|
||||
EXISTS: true,
|
||||
}
|
||||
}
|
||||
arr = append(arr[:num], append(args[1:], arr[num:]...)...)
|
||||
val.obj["length"] = len(arr)
|
||||
val.obj["__value__"] = arr
|
||||
return nil, ArErr{}
|
||||
},
|
||||
}
|
||||
val.obj["pop"] = builtinFunc{
|
||||
"pop",
|
||||
func(args ...any) (any, ArErr) {
|
||||
if len(args) > 1 {
|
||||
return nil, ArErr{
|
||||
TYPE: "TypeError",
|
||||
message: "too many arguments",
|
||||
EXISTS: true,
|
||||
}
|
||||
}
|
||||
if len(args) == 1 {
|
||||
if typeof(args[0]) != "number" {
|
||||
return nil, ArErr{
|
||||
TYPE: "TypeError",
|
||||
message: "argument must be a number",
|
||||
EXISTS: true,
|
||||
}
|
||||
}
|
||||
if !args[0].(number).IsInt() {
|
||||
return nil, ArErr{
|
||||
TYPE: "TypeError",
|
||||
message: "argument must be an integer",
|
||||
EXISTS: true,
|
||||
}
|
||||
}
|
||||
num := int(args[0].(number).Num().Int64())
|
||||
if num < 0 || num >= len(arr) {
|
||||
return nil, ArErr{
|
||||
TYPE: "IndexError",
|
||||
message: "index out of range",
|
||||
EXISTS: true,
|
||||
}
|
||||
}
|
||||
v := arr[num]
|
||||
arr = append(arr[:num], arr[num+1:]...)
|
||||
val.obj["length"] = len(arr)
|
||||
val.obj["__value__"] = arr
|
||||
return v, ArErr{}
|
||||
}
|
||||
v := arr[len(arr)-1]
|
||||
arr = arr[:len(arr)-1]
|
||||
val.obj["length"] = len(arr)
|
||||
val.obj["__value__"] = arr
|
||||
return v, ArErr{}
|
||||
},
|
||||
}
|
||||
val.obj["clear"] = builtinFunc{
|
||||
"clear",
|
||||
func(args ...any) (any, ArErr) {
|
||||
if len(args) != 0 {
|
||||
return nil, ArErr{
|
||||
TYPE: "TypeError",
|
||||
message: "too many arguments",
|
||||
EXISTS: true,
|
||||
}
|
||||
}
|
||||
arr = []any{}
|
||||
val.obj["length"] = len(arr)
|
||||
val.obj["__value__"] = arr
|
||||
return nil, ArErr{}
|
||||
},
|
||||
}
|
||||
val.obj["extend"] = builtinFunc{
|
||||
"extend",
|
||||
func(args ...any) (any, ArErr) {
|
||||
if len(args) != 1 {
|
||||
return nil, ArErr{
|
||||
TYPE: "TypeError",
|
||||
message: "missing argument",
|
||||
EXISTS: true,
|
||||
}
|
||||
}
|
||||
if typeof(args[0]) != "array" {
|
||||
return nil, ArErr{
|
||||
TYPE: "TypeError",
|
||||
message: "argument must be an array",
|
||||
EXISTS: true,
|
||||
}
|
||||
}
|
||||
arr = append(arr, args[0].(ArObject).obj["__value__"].([]any)...)
|
||||
val.obj["length"] = len(arr)
|
||||
val.obj["__value__"] = arr
|
||||
return nil, ArErr{}
|
||||
},
|
||||
}
|
||||
val.obj["map"] = builtinFunc{
|
||||
"map",
|
||||
func(args ...any) (any, ArErr) {
|
||||
if len(args) != 1 {
|
||||
return nil, ArErr{
|
||||
TYPE: "TypeError",
|
||||
message: "missing argument",
|
||||
EXISTS: true,
|
||||
}
|
||||
}
|
||||
if typeof(args[0]) != "function" {
|
||||
return nil, ArErr{
|
||||
TYPE: "TypeError",
|
||||
message: "argument must be a function",
|
||||
EXISTS: true,
|
||||
}
|
||||
}
|
||||
newarr := []any{}
|
||||
for _, v := range arr {
|
||||
vv, err := runCall(call{
|
||||
args[0],
|
||||
[]any{v}, "", 0, "",
|
||||
}, stack{vars, newscope()}, 0)
|
||||
if err.EXISTS {
|
||||
return nil, err
|
||||
}
|
||||
newarr = append(newarr, vv)
|
||||
}
|
||||
return ArArray(newarr), ArErr{}
|
||||
},
|
||||
}
|
||||
return val
|
||||
}
|
||||
|
||||
func potentialAnyArrayToArArray(arr any) any {
|
||||
switch arr := arr.(type) {
|
||||
case []any:
|
||||
return ArArray(arr)
|
||||
default:
|
||||
return arr
|
||||
}
|
||||
}
|
||||
|
||||
func parseArray(code UNPARSEcode, index int, codelines []UNPARSEcode) (any, bool, ArErr, int) {
|
||||
trimmed := strings.TrimSpace(code.code)
|
||||
trimmed = trimmed[1 : len(trimmed)-1]
|
||||
@@ -27,14 +254,14 @@ func parseArray(code UNPARSEcode, index int, codelines []UNPARSEcode) (any, bool
|
||||
}, worked, err, 1
|
||||
}
|
||||
|
||||
func runArray(a CreateArray, stack stack, stacklevel int) ([]any, ArErr) {
|
||||
var array ArArray
|
||||
func runArray(a CreateArray, stack stack, stacklevel int) (ArObject, ArErr) {
|
||||
var array []any
|
||||
for _, val := range a.value {
|
||||
val, err := runVal(val, stack, stacklevel+1)
|
||||
if err.EXISTS {
|
||||
return nil, err
|
||||
return ArObject{}, err
|
||||
}
|
||||
array = append(array, val)
|
||||
}
|
||||
return array, ArErr{}
|
||||
return ArArray(array), ArErr{}
|
||||
}
|
||||
|
||||
@@ -12,8 +12,11 @@ func anyToBool(x any) bool {
|
||||
return x
|
||||
case nil:
|
||||
return false
|
||||
case ArMap:
|
||||
return len(x) != 0
|
||||
case ArObject:
|
||||
if x.TYPE == "array" {
|
||||
return len(x.obj["__value__"].([]any)) != 0
|
||||
}
|
||||
return len(x.obj) != 0
|
||||
case builtinFunc:
|
||||
return true
|
||||
case Callable:
|
||||
|
||||
156
src/built-ins.go
156
src/built-ins.go
@@ -1,97 +1,97 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var vars = scope{}
|
||||
var vars = Map(anymap{})
|
||||
|
||||
func init() {
|
||||
vars["global"] = vars
|
||||
vars["term"] = ArTerm
|
||||
vars["input"] = builtinFunc{"input", ArgonInput}
|
||||
vars["number"] = builtinFunc{"number", ArgonNumber}
|
||||
vars["string"] = builtinFunc{"string", ArgonString}
|
||||
vars["infinity"] = infinity
|
||||
vars["length"] = builtinFunc{"length", func(a ...any) (any, ArErr) {
|
||||
vars.obj["global"] = vars
|
||||
vars.obj["term"] = ArTerm
|
||||
vars.obj["input"] = builtinFunc{"input", ArgonInput}
|
||||
vars.obj["number"] = builtinFunc{"number", ArgonNumber}
|
||||
vars.obj["string"] = builtinFunc{"string", ArgonString}
|
||||
vars.obj["infinity"] = infinity
|
||||
vars.obj["length"] = builtinFunc{"length", func(a ...any) (any, ArErr) {
|
||||
switch x := a[0].(type) {
|
||||
case string:
|
||||
return len(x), ArErr{}
|
||||
case ArMap:
|
||||
return len(x), ArErr{}
|
||||
case ArObject:
|
||||
if x.TYPE == "array" {
|
||||
return len(x.obj["__value__"].([]any)), ArErr{}
|
||||
}
|
||||
return len(x.obj), ArErr{}
|
||||
}
|
||||
return nil, ArErr{TYPE: "TypeError", message: "Cannot get length of " + typeof(a[0]), EXISTS: true}
|
||||
}}
|
||||
vars["map"] = builtinFunc{"map", func(a ...any) (any, ArErr) {
|
||||
vars.obj["map"] = builtinFunc{"map", func(a ...any) (any, ArErr) {
|
||||
if len(a) == 0 {
|
||||
return ArMap{}, ArErr{}
|
||||
return Map(anymap{}), ArErr{}
|
||||
}
|
||||
switch x := a[0].(type) {
|
||||
case ArMap:
|
||||
case ArObject:
|
||||
if x.TYPE == "array" {
|
||||
newmap := anymap{}
|
||||
for i, v := range x.obj["__value__"].([]any) {
|
||||
switch y := v.(type) {
|
||||
case []any:
|
||||
if len(y) == 2 {
|
||||
if isUnhashable(y[0]) {
|
||||
return nil, ArErr{TYPE: "TypeError", message: "Cannot use unhashable value as key: " + typeof(y[0]), EXISTS: true}
|
||||
}
|
||||
newmap[y[0]] = y[1]
|
||||
continue
|
||||
}
|
||||
}
|
||||
newmap[i] = v
|
||||
}
|
||||
return Map(newmap), ArErr{}
|
||||
}
|
||||
return x, ArErr{}
|
||||
case string:
|
||||
newmap := ArMap{}
|
||||
newmap := anymap{}
|
||||
for i, v := range x {
|
||||
newmap[i] = string(v)
|
||||
}
|
||||
return newmap, ArErr{}
|
||||
case ArArray:
|
||||
newmap := ArMap{}
|
||||
for i, v := range x {
|
||||
switch y := v.(type) {
|
||||
case ArArray:
|
||||
if len(y) == 2 {
|
||||
if isUnhashable(y[0]) {
|
||||
return nil, ArErr{TYPE: "TypeError", message: "Cannot use unhashable value as key: " + typeof(y[0]), EXISTS: true}
|
||||
}
|
||||
newmap[y[0]] = y[1]
|
||||
continue
|
||||
}
|
||||
}
|
||||
newmap[i] = v
|
||||
}
|
||||
return newmap, ArErr{}
|
||||
return Map(newmap), ArErr{}
|
||||
}
|
||||
return nil, ArErr{TYPE: "TypeError", message: "Cannot create map from '" + typeof(a[0]) + "'", EXISTS: true}
|
||||
}}
|
||||
vars["array"] = builtinFunc{"array", func(a ...any) (any, ArErr) {
|
||||
vars.obj["array"] = builtinFunc{"array", func(a ...any) (any, ArErr) {
|
||||
if len(a) == 0 {
|
||||
return ArArray{}, ArErr{}
|
||||
return ArArray([]any{}), ArErr{}
|
||||
}
|
||||
switch x := a[0].(type) {
|
||||
case ArArray:
|
||||
return x, ArErr{}
|
||||
case string:
|
||||
newarray := ArArray{}
|
||||
newarray := []any{}
|
||||
for _, v := range x {
|
||||
newarray = append(newarray, string(v))
|
||||
}
|
||||
return newarray, ArErr{}
|
||||
case ArMap:
|
||||
newarray := ArArray{}
|
||||
for key, val := range x {
|
||||
newarray = append(newarray, ArArray{key, val})
|
||||
return ArArray(newarray), ArErr{}
|
||||
case ArObject:
|
||||
if x.TYPE == "array" {
|
||||
return x, ArErr{}
|
||||
}
|
||||
return newarray, ArErr{}
|
||||
newarray := []any{}
|
||||
for key, val := range x.obj {
|
||||
newarray = append(newarray, []any{key, val})
|
||||
}
|
||||
return ArArray(newarray), ArErr{}
|
||||
}
|
||||
return nil, ArErr{TYPE: "TypeError", message: "Cannot create array from '" + typeof(a[0]) + "'", EXISTS: true}
|
||||
}}
|
||||
vars["boolean"] = builtinFunc{"boolean", func(a ...any) (any, ArErr) {
|
||||
vars.obj["boolean"] = builtinFunc{"boolean", func(a ...any) (any, ArErr) {
|
||||
if len(a) == 0 {
|
||||
return false, ArErr{}
|
||||
}
|
||||
return anyToBool(a[0]), ArErr{}
|
||||
}}
|
||||
vars["time"] = ArTime
|
||||
vars["PI"] = PI
|
||||
vars["π"] = PI
|
||||
vars["e"] = e
|
||||
vars["ln"] = builtinFunc{"ln", ArgonLn}
|
||||
vars["log"] = builtinFunc{"log", ArgonLog}
|
||||
vars["logN"] = builtinFunc{"logN", ArgonLogN}
|
||||
vars["thread"] = builtinFunc{"thread", ArThread}
|
||||
vars["round"] = builtinFunc{"round", func(a ...any) (any, ArErr) {
|
||||
vars.obj["time"] = ArTime
|
||||
vars.obj["PI"] = PI
|
||||
vars.obj["π"] = PI
|
||||
vars.obj["e"] = e
|
||||
vars.obj["ln"] = builtinFunc{"ln", ArgonLn}
|
||||
vars.obj["log"] = builtinFunc{"log", ArgonLog}
|
||||
vars.obj["logN"] = builtinFunc{"logN", ArgonLogN}
|
||||
vars.obj["thread"] = builtinFunc{"thread", ArThread}
|
||||
vars.obj["round"] = builtinFunc{"round", func(a ...any) (any, ArErr) {
|
||||
if len(a) == 0 {
|
||||
return nil, ArErr{TYPE: "round", message: "round takes 1 argument",
|
||||
EXISTS: true}
|
||||
@@ -115,7 +115,7 @@ func init() {
|
||||
}
|
||||
return nil, ArErr{TYPE: "TypeError", message: "Cannot round '" + typeof(a[0]) + "'", EXISTS: true}
|
||||
}}
|
||||
vars["floor"] = builtinFunc{"floor", func(a ...any) (any, ArErr) {
|
||||
vars.obj["floor"] = builtinFunc{"floor", func(a ...any) (any, ArErr) {
|
||||
if len(a) == 0 {
|
||||
return nil, ArErr{TYPE: "floor", message: "floor takes 1 argument",
|
||||
EXISTS: true}
|
||||
@@ -126,7 +126,7 @@ func init() {
|
||||
}
|
||||
return nil, ArErr{TYPE: "TypeError", message: "Cannot floor '" + typeof(a[0]) + "'", EXISTS: true}
|
||||
}}
|
||||
vars["ceil"] = builtinFunc{"ceil", func(a ...any) (any, ArErr) {
|
||||
vars.obj["ceil"] = builtinFunc{"ceil", func(a ...any) (any, ArErr) {
|
||||
if len(a) == 0 {
|
||||
return nil, ArErr{TYPE: "ceil", message: "ceil takes 1 argument",
|
||||
EXISTS: true}
|
||||
@@ -138,36 +138,10 @@ func init() {
|
||||
}
|
||||
return nil, ArErr{TYPE: "TypeError", message: "Cannot ceil '" + typeof(a[0]) + "'", EXISTS: true}
|
||||
}}
|
||||
vars["append"] = builtinFunc{"append", func(a ...any) (any, ArErr) {
|
||||
if len(a) != 2 {
|
||||
return nil, ArErr{TYPE: "append", message: "append takes 2 arguments, got " + fmt.Sprint(len(a)),
|
||||
EXISTS: true}
|
||||
}
|
||||
switch x := a[0].(type) {
|
||||
case ArArray:
|
||||
return append(x, a[1]), ArErr{}
|
||||
case string:
|
||||
if typeof(a[1]) != "string" {
|
||||
return nil, ArErr{TYPE: "TypeError", message: "Cannot append '" + typeof(a[1]) + "' to string", EXISTS: true}
|
||||
}
|
||||
return strings.Join([]string{x, a[1].(string)}, ""), ArErr{}
|
||||
case ArMap:
|
||||
if typeof(a[1]) != "array" {
|
||||
return nil, ArErr{TYPE: "TypeError", message: "Cannot append '" + typeof(a[1]) + "' to map", EXISTS: true}
|
||||
}
|
||||
y := a[1].(ArArray)
|
||||
if len(y) != 2 {
|
||||
return nil, ArErr{TYPE: "TypeError", message: "Cannot append '" + typeof(a[1]) + "' to map", EXISTS: true}
|
||||
}
|
||||
x[y[0]] = y[1]
|
||||
return x, ArErr{}
|
||||
}
|
||||
return nil, ArErr{TYPE: "TypeError", message: "Cannot append to '" + typeof(a[0]) + "'", EXISTS: true}
|
||||
}}
|
||||
vars["sqrt"] = builtinFunc{"sqrt", ArgonSqrt}
|
||||
vars["file"] = ArFile
|
||||
vars["random"] = ArRandom
|
||||
vars["json"] = ArJSON
|
||||
vars["sin"] = ArSin
|
||||
vars["arcsin"] = ArArcsin
|
||||
vars.obj["sqrt"] = builtinFunc{"sqrt", ArgonSqrt}
|
||||
vars.obj["file"] = ArFile
|
||||
vars.obj["random"] = ArRandom
|
||||
vars.obj["json"] = ArJSON
|
||||
vars.obj["sin"] = ArSin
|
||||
vars.obj["arcsin"] = ArArcsin
|
||||
}
|
||||
|
||||
20
src/call.go
20
src/call.go
@@ -15,6 +15,14 @@ type call struct {
|
||||
path string
|
||||
}
|
||||
|
||||
type Callable struct {
|
||||
params []string
|
||||
run any
|
||||
code string
|
||||
stack stack
|
||||
line int
|
||||
}
|
||||
|
||||
func isCall(code UNPARSEcode) bool {
|
||||
return callCompile.MatchString(code.code)
|
||||
}
|
||||
@@ -30,7 +38,7 @@ func parseCall(code UNPARSEcode, index int, codelines []UNPARSEcode) (any, bool,
|
||||
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, true)
|
||||
args, success, argserr := getValuesFromLetter(argstr, ",", index, codelines, false)
|
||||
arguments = args
|
||||
if !success {
|
||||
if i == len(splitby)-1 {
|
||||
@@ -68,13 +76,13 @@ func runCall(c call, stack stack, stacklevel int) (any, ArErr) {
|
||||
return nil, err
|
||||
}
|
||||
switch x := callable_.(type) {
|
||||
case ArMap:
|
||||
callable_ = x["__call__"]
|
||||
case ArObject:
|
||||
callable_ = x.obj["__call__"]
|
||||
}
|
||||
callable = callable_
|
||||
}
|
||||
args := []any{}
|
||||
level := append(stack, scope{})
|
||||
level := append(stack, newscope())
|
||||
for _, arg := range c.args {
|
||||
resp, err := runVal(arg, level, stacklevel+1)
|
||||
if err.EXISTS {
|
||||
@@ -101,9 +109,9 @@ func runCall(c call, stack stack, stacklevel int) (any, ArErr) {
|
||||
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}
|
||||
}
|
||||
level := scope{}
|
||||
level := newscope()
|
||||
for i, param := range x.params {
|
||||
level[param] = args[i]
|
||||
level.obj[param] = args[i]
|
||||
}
|
||||
resp, err := runVal(x.run, append(x.stack, level), stacklevel+1)
|
||||
return ThrowOnNonLoop(openReturn(resp), err)
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
package main
|
||||
|
||||
type Callable struct {
|
||||
params []string
|
||||
run any
|
||||
code string
|
||||
stack stack
|
||||
line int
|
||||
}
|
||||
@@ -49,7 +49,7 @@ func parseDoWrap(code UNPARSEcode, index int, codelines []UNPARSEcode) (any, boo
|
||||
}
|
||||
|
||||
func runDoWrap(d dowrap, stack stack, stacklevel int) (any, ArErr) {
|
||||
newstack := append(stack, scope{})
|
||||
newstack := append(stack, newscope())
|
||||
for _, v := range d.run {
|
||||
val, err := runVal(v, newstack, stacklevel+1)
|
||||
if err.EXISTS {
|
||||
|
||||
36
src/file.go
36
src/file.go
@@ -7,10 +7,10 @@ import (
|
||||
"os"
|
||||
)
|
||||
|
||||
var ArFile = ArMap{
|
||||
var ArFile = Map(anymap{
|
||||
"read": builtinFunc{"read", ArRead},
|
||||
"write": builtinFunc{"write", ArWrite},
|
||||
}
|
||||
})
|
||||
|
||||
func readtext(file *os.File) (string, error) {
|
||||
var buf bytes.Buffer
|
||||
@@ -23,68 +23,68 @@ func readtext(file *os.File) (string, error) {
|
||||
|
||||
func ArRead(args ...any) (any, ArErr) {
|
||||
if len(args) != 1 {
|
||||
return ArMap{}, ArErr{TYPE: "Runtime Error", message: "read takes 1 argument, got " + fmt.Sprint(len(args)), EXISTS: true}
|
||||
return ArObject{}, ArErr{TYPE: "Runtime Error", message: "read takes 1 argument, got " + fmt.Sprint(len(args)), EXISTS: true}
|
||||
}
|
||||
if typeof(args[0]) != "string" {
|
||||
return ArMap{}, ArErr{TYPE: "Runtime Error", message: "read takes a string not type '" + typeof(args[0]) + "'", EXISTS: true}
|
||||
return ArObject{}, ArErr{TYPE: "Runtime Error", message: "read takes a string not type '" + typeof(args[0]) + "'", EXISTS: true}
|
||||
}
|
||||
filename := args[0].(string)
|
||||
file, err := os.Open(filename)
|
||||
if err != nil {
|
||||
return ArMap{}, ArErr{TYPE: "Runtime Error", message: err.Error(), EXISTS: true}
|
||||
return ArObject{}, ArErr{TYPE: "Runtime Error", message: err.Error(), EXISTS: true}
|
||||
}
|
||||
return ArMap{
|
||||
return Map(anymap{
|
||||
"text": builtinFunc{"text", func(...any) (any, ArErr) {
|
||||
text, err := readtext(file)
|
||||
if err != nil {
|
||||
return ArMap{}, ArErr{TYPE: "Runtime Error", message: err.Error(), EXISTS: true}
|
||||
return ArObject{}, ArErr{TYPE: "Runtime Error", message: err.Error(), EXISTS: true}
|
||||
}
|
||||
return text, ArErr{}
|
||||
}},
|
||||
"json": builtinFunc{"json", func(...any) (any, ArErr) {
|
||||
text, err := readtext(file)
|
||||
if err != nil {
|
||||
return ArMap{}, ArErr{TYPE: "Runtime Error", message: err.Error(), EXISTS: true}
|
||||
return ArObject{}, ArErr{TYPE: "Runtime Error", message: err.Error(), EXISTS: true}
|
||||
}
|
||||
return jsonparse(text), ArErr{}
|
||||
}},
|
||||
}, ArErr{}
|
||||
}), ArErr{}
|
||||
}
|
||||
|
||||
func ArWrite(args ...any) (any, ArErr) {
|
||||
if len(args) != 1 {
|
||||
return ArMap{}, ArErr{TYPE: "Runtime Error", message: "write takes 1 argument, got " + fmt.Sprint(len(args)), EXISTS: true}
|
||||
return ArObject{}, ArErr{TYPE: "Runtime Error", message: "write takes 1 argument, got " + fmt.Sprint(len(args)), EXISTS: true}
|
||||
}
|
||||
if typeof(args[0]) != "string" {
|
||||
return ArMap{}, ArErr{TYPE: "Runtime Error", message: "write takes a string not type '" + typeof(args[0]) + "'", EXISTS: true}
|
||||
return ArObject{}, ArErr{TYPE: "Runtime Error", message: "write takes a string not type '" + typeof(args[0]) + "'", EXISTS: true}
|
||||
}
|
||||
filename := args[0].(string)
|
||||
file, err := os.Create(filename)
|
||||
if err != nil {
|
||||
return ArMap{}, ArErr{TYPE: "Runtime Error", message: err.Error(), EXISTS: true}
|
||||
return ArObject{}, ArErr{TYPE: "Runtime Error", message: err.Error(), EXISTS: true}
|
||||
}
|
||||
return ArMap{
|
||||
return Map(anymap{
|
||||
"text": builtinFunc{"text", func(args ...any) (any, ArErr) {
|
||||
if len(args) != 1 {
|
||||
return ArMap{}, ArErr{TYPE: "Runtime Error", message: "text takes 1 argument, got " + fmt.Sprint(len(args)), EXISTS: true}
|
||||
return ArObject{}, ArErr{TYPE: "Runtime Error", message: "text takes 1 argument, got " + fmt.Sprint(len(args)), EXISTS: true}
|
||||
}
|
||||
if typeof(args[0]) != "string" {
|
||||
return ArMap{}, ArErr{TYPE: "Runtime Error", message: "text takes a string not type '" + typeof(args[0]) + "'", EXISTS: true}
|
||||
return ArObject{}, ArErr{TYPE: "Runtime Error", message: "text takes a string not type '" + typeof(args[0]) + "'", EXISTS: true}
|
||||
}
|
||||
file.Write([]byte(args[0].(string)))
|
||||
return nil, ArErr{}
|
||||
}},
|
||||
"json": builtinFunc{"json", func(args ...any) (any, ArErr) {
|
||||
if len(args) != 1 {
|
||||
return ArMap{}, ArErr{TYPE: "Runtime Error", message: "json takes 1 argument, got " + fmt.Sprint(len(args)), EXISTS: true}
|
||||
return ArObject{}, ArErr{TYPE: "Runtime Error", message: "json takes 1 argument, got " + fmt.Sprint(len(args)), EXISTS: true}
|
||||
}
|
||||
jsonstr, err := jsonstringify(args[0], 0)
|
||||
if err != nil {
|
||||
return ArMap{}, ArErr{TYPE: "Runtime Error", message: err.Error(), EXISTS: true}
|
||||
return ArObject{}, ArErr{TYPE: "Runtime Error", message: err.Error(), EXISTS: true}
|
||||
}
|
||||
file.Write([]byte(jsonstr))
|
||||
return nil, ArErr{}
|
||||
}},
|
||||
}, ArErr{}
|
||||
}), ArErr{}
|
||||
|
||||
}
|
||||
|
||||
@@ -5,15 +5,19 @@ import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
type ArMap = map[any]any
|
||||
type ArArray = []any
|
||||
type ArObject struct {
|
||||
TYPE string
|
||||
obj anymap
|
||||
}
|
||||
|
||||
type anymap map[any]any
|
||||
|
||||
var mapGetCompile = makeRegex(`(.|\n)+\.([a-zA-Z_]|(\p{L}\p{M}*))([a-zA-Z0-9_]|(\p{L}\p{M}*))*( *)`)
|
||||
var indexGetCompile = makeRegex(`(.|\n)+\[(.|\n)+\]( *)`)
|
||||
|
||||
type ArMapGet struct {
|
||||
VAL any
|
||||
args ArArray
|
||||
args []any
|
||||
index bool
|
||||
line int
|
||||
code string
|
||||
@@ -26,7 +30,14 @@ func mapGet(r ArMapGet, stack stack, stacklevel int) (any, ArErr) {
|
||||
return nil, err
|
||||
}
|
||||
switch m := resp.(type) {
|
||||
case ArMap:
|
||||
case ArObject:
|
||||
switch m.TYPE {
|
||||
case "array":
|
||||
resp, err := getFromArArray(m, r, stack, stacklevel+1)
|
||||
if !err.EXISTS {
|
||||
return resp, err
|
||||
}
|
||||
}
|
||||
if len(r.args) > 1 {
|
||||
return nil, ArErr{
|
||||
"IndexError",
|
||||
@@ -51,7 +62,7 @@ func mapGet(r ArMapGet, stack stack, stacklevel int) (any, ArErr) {
|
||||
true,
|
||||
}
|
||||
}
|
||||
if _, ok := m[key]; !ok {
|
||||
if _, ok := m.obj[key]; !ok {
|
||||
return nil, ArErr{
|
||||
"KeyError",
|
||||
"key '" + fmt.Sprint(key) + "' not found",
|
||||
@@ -61,12 +72,15 @@ func mapGet(r ArMapGet, stack stack, stacklevel int) (any, ArErr) {
|
||||
true,
|
||||
}
|
||||
}
|
||||
return m[key], ArErr{}
|
||||
|
||||
case ArArray:
|
||||
return getFromArArray(m, r, stack, stacklevel)
|
||||
return potentialAnyArrayToArArray(m.obj[key]), ArErr{}
|
||||
case string:
|
||||
return getFromString(m, r, stack, stacklevel)
|
||||
if val, ok := r.args[0].(string); !r.index && ok {
|
||||
switch val {
|
||||
case "length":
|
||||
return len(m), ArErr{}
|
||||
}
|
||||
}
|
||||
return getFromString(m, r, stack, stacklevel+1)
|
||||
}
|
||||
|
||||
key, err := runVal(r.args[0], stack, stacklevel+1)
|
||||
@@ -84,9 +98,9 @@ func mapGet(r ArMapGet, stack stack, stacklevel int) (any, ArErr) {
|
||||
}
|
||||
|
||||
func classVal(r any) any {
|
||||
if _, ok := r.(ArMap); ok {
|
||||
if _, ok := r.(ArMap)["__value__"]; ok {
|
||||
return r.(ArMap)["__value__"]
|
||||
if j, ok := r.(ArObject); ok {
|
||||
if _, ok := j.obj["__value__"]; ok {
|
||||
return j.obj["__value__"]
|
||||
}
|
||||
}
|
||||
return r
|
||||
@@ -105,7 +119,7 @@ func mapGetParse(code UNPARSEcode, index int, codelines []UNPARSEcode) (ArMapGet
|
||||
if !worked {
|
||||
return ArMapGet{}, false, err, i
|
||||
}
|
||||
return ArMapGet{resp, ArArray{key}, false, code.line, code.realcode, code.path}, true, ArErr{}, 1
|
||||
return ArMapGet{resp, []any{key}, false, code.line, code.realcode, code.path}, true, ArErr{}, 1
|
||||
}
|
||||
|
||||
func isIndexGet(code UNPARSEcode) bool {
|
||||
@@ -126,7 +140,6 @@ func indexGetParse(code UNPARSEcode, index int, codelines []UNPARSEcode) (ArMapG
|
||||
}
|
||||
continue
|
||||
}
|
||||
fmt.Println(args)
|
||||
if len(args) > 3 {
|
||||
return ArMapGet{}, false, ArErr{
|
||||
"SyntaxError",
|
||||
@@ -161,7 +174,7 @@ func isUnhashable(val any) bool {
|
||||
return keytype == "array" || keytype == "map"
|
||||
}
|
||||
|
||||
func getFromArArray(m []any, r ArMapGet, stack stack, stacklevel int) (ArArray, ArErr) {
|
||||
func getFromArArray(m ArObject, r ArMapGet, stack stack, stacklevel int) (ArObject, ArErr) {
|
||||
var (
|
||||
start int = 0
|
||||
end any = nil
|
||||
@@ -170,12 +183,12 @@ func getFromArArray(m []any, r ArMapGet, stack stack, stacklevel int) (ArArray,
|
||||
{
|
||||
startval, err := runVal(r.args[0], stack, stacklevel+1)
|
||||
if err.EXISTS {
|
||||
return nil, err
|
||||
return ArObject{}, err
|
||||
}
|
||||
if startval == nil {
|
||||
start = 0
|
||||
} else if typeof(startval) != "number" && !startval.(number).IsInt() {
|
||||
return nil, ArErr{
|
||||
} else if typeof(startval) != "number" || !startval.(number).IsInt() {
|
||||
return ArObject{}, ArErr{
|
||||
"TypeError",
|
||||
"slice index must be an integer",
|
||||
r.line,
|
||||
@@ -190,12 +203,12 @@ func getFromArArray(m []any, r ArMapGet, stack stack, stacklevel int) (ArArray,
|
||||
if len(r.args) > 1 {
|
||||
endval, err := runVal(r.args[1], stack, stacklevel+1)
|
||||
if err.EXISTS {
|
||||
return nil, err
|
||||
return ArObject{}, err
|
||||
}
|
||||
if endval == nil {
|
||||
end = len(m)
|
||||
end = m.obj["length"]
|
||||
} else if typeof(endval) != "number" && !endval.(number).IsInt() {
|
||||
return nil, ArErr{
|
||||
return ArObject{}, ArErr{
|
||||
"TypeError",
|
||||
"slice ending index must be an integer",
|
||||
r.line,
|
||||
@@ -210,12 +223,12 @@ func getFromArArray(m []any, r ArMapGet, stack stack, stacklevel int) (ArArray,
|
||||
if len(r.args) > 2 {
|
||||
stepval, err := runVal(r.args[2], stack, stacklevel+1)
|
||||
if err.EXISTS {
|
||||
return nil, err
|
||||
return ArObject{}, err
|
||||
}
|
||||
if stepval == nil {
|
||||
step = 1
|
||||
} else if typeof(stepval) != "number" && !stepval.(number).IsInt() {
|
||||
return nil, ArErr{
|
||||
return ArObject{}, ArErr{
|
||||
"TypeError",
|
||||
"slice step must be an integer",
|
||||
r.line,
|
||||
@@ -228,29 +241,27 @@ func getFromArArray(m []any, r ArMapGet, stack stack, stacklevel int) (ArArray,
|
||||
}
|
||||
}
|
||||
if start < 0 {
|
||||
start = len(m) + start
|
||||
start = m.obj["length"].(int) + start
|
||||
}
|
||||
if _, ok := end.(int); ok && end.(int) < 0 {
|
||||
end = len(m) + end.(int)
|
||||
end = m.obj["length"].(int) + end.(int)
|
||||
}
|
||||
|
||||
fmt.Println(start, end, step)
|
||||
if end == nil {
|
||||
return ArArray{m[start]}, ArErr{}
|
||||
return ArArray([]any{m.obj["__value__"].([]any)[start]}), ArErr{}
|
||||
} else if step == 1 {
|
||||
return m[start:end.(int)], ArErr{}
|
||||
return ArArray([]any{m.obj["__value__"].([]any)[start:end.(int)]}), ArErr{}
|
||||
} else {
|
||||
output := ArArray{}
|
||||
output := []any{}
|
||||
if step > 0 {
|
||||
for i := start; i < end.(int); i += step {
|
||||
output = append(output, m[i])
|
||||
output = append(output, m.obj["__value__"].([]any)[i])
|
||||
}
|
||||
} else {
|
||||
for i := end.(int) - 1; i >= start; i += step {
|
||||
output = append(output, m[i])
|
||||
output = append(output, m.obj["__value__"].([]any)[i])
|
||||
}
|
||||
}
|
||||
return (output), ArErr{}
|
||||
return ArArray(output), ArErr{}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -267,7 +278,7 @@ func getFromString(m string, r ArMapGet, stack stack, stacklevel int) (string, A
|
||||
}
|
||||
if startval == nil {
|
||||
start = 0
|
||||
} else if typeof(startval) != "number" && !startval.(number).IsInt() {
|
||||
} else if typeof(startval) != "number" || !startval.(number).IsInt() {
|
||||
return "", ArErr{
|
||||
"TypeError",
|
||||
"slice index must be an integer",
|
||||
@@ -326,8 +337,6 @@ func getFromString(m string, r ArMapGet, stack stack, stacklevel int) (string, A
|
||||
if _, ok := end.(int); ok && end.(int) < 0 {
|
||||
end = len(m) + end.(int)
|
||||
}
|
||||
|
||||
fmt.Println(start, end, step)
|
||||
if end == nil {
|
||||
return string(m[start]), ArErr{}
|
||||
} else if step == 1 {
|
||||
|
||||
@@ -118,7 +118,7 @@ func parseIfStatement(code UNPARSEcode, index int, codeline []UNPARSEcode) (ifst
|
||||
|
||||
func runIfStatement(code ifstatement, stack stack, stacklevel int) (any, ArErr) {
|
||||
for _, condition := range code.conditions {
|
||||
newstack := append(stack, scope{})
|
||||
newstack := append(stack, newscope())
|
||||
resp, err := runVal(condition.condition, newstack, stacklevel+1)
|
||||
if err.EXISTS {
|
||||
return nil, err
|
||||
@@ -128,7 +128,7 @@ func runIfStatement(code ifstatement, stack stack, stacklevel int) (any, ArErr)
|
||||
}
|
||||
}
|
||||
if code.ELSE != nil {
|
||||
return runVal(code.ELSE, append(stack, scope{}), stacklevel+1)
|
||||
return runVal(code.ELSE, append(stack, newscope()), stacklevel+1)
|
||||
}
|
||||
return nil, ArErr{}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,9 @@ import (
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
var imported = make(map[string]ArObject)
|
||||
var importing = make(map[string]bool)
|
||||
|
||||
func FileExists(filename string) bool {
|
||||
if _, err := os.Stat(filename); err == nil {
|
||||
return true
|
||||
@@ -44,7 +47,7 @@ func readFile(path string) []UNPARSEcode {
|
||||
return output
|
||||
}
|
||||
|
||||
func importMod(realpath string, origin string) (scope, ArErr) {
|
||||
func importMod(realpath string, origin string, main bool) (ArObject, ArErr) {
|
||||
extention := filepath.Ext(realpath)
|
||||
path := realpath
|
||||
if extention == "" {
|
||||
@@ -52,13 +55,13 @@ func importMod(realpath string, origin string) (scope, ArErr) {
|
||||
}
|
||||
ex, err := os.Getwd()
|
||||
if err != nil {
|
||||
return nil, ArErr{"Import Error", err.Error(), 0, realpath, "", true}
|
||||
return ArObject{}, ArErr{TYPE: "Import Error", message: "Could not get working directory", EXISTS: true}
|
||||
}
|
||||
executable, err := os.Executable()
|
||||
exc, err := os.Executable()
|
||||
if err != nil {
|
||||
return nil, ArErr{"Import Error", err.Error(), 0, realpath, "", true}
|
||||
return ArObject{}, ArErr{TYPE: "Import Error", message: "Could not get executable", EXISTS: true}
|
||||
}
|
||||
executable = filepath.Dir(executable)
|
||||
executable := filepath.Dir(exc)
|
||||
isABS := filepath.IsAbs(path)
|
||||
var pathsToTest []string
|
||||
if isABS {
|
||||
@@ -90,18 +93,52 @@ func importMod(realpath string, origin string) (scope, ArErr) {
|
||||
}
|
||||
|
||||
if !found {
|
||||
return nil, ArErr{"Import Error", "File does not exist: " + realpath, 0, realpath, "", true}
|
||||
return ArObject{}, ArErr{TYPE: "Import Error", message: "File does not exist: " + realpath, EXISTS: true}
|
||||
} else if importing[p] {
|
||||
return ArObject{}, ArErr{TYPE: "Import Error", message: "Circular import: " + realpath, EXISTS: true}
|
||||
} else if _, ok := imported[p]; ok {
|
||||
return imported[p], ArErr{}
|
||||
}
|
||||
importing[p] = true
|
||||
codelines := readFile(p)
|
||||
|
||||
translated, translationerr := translate(codelines)
|
||||
if translationerr.EXISTS {
|
||||
return nil, translationerr
|
||||
return ArObject{}, translationerr
|
||||
}
|
||||
global := scope{}
|
||||
_, runimeErr, _ := run(translated, stack{vars, global})
|
||||
ArgsArArray := []any{}
|
||||
for _, arg := range Args[1:] {
|
||||
ArgsArArray = append(ArgsArArray, arg)
|
||||
}
|
||||
global := newscope()
|
||||
localvars := Map(anymap{
|
||||
"program": Map(anymap{
|
||||
"args": ArArray(ArgsArArray),
|
||||
"origin": origin,
|
||||
"import": builtinFunc{"import", func(args ...any) (any, ArErr) {
|
||||
if len(args) != 1 {
|
||||
return nil, ArErr{"Import Error", "Invalid number of arguments", 0, realpath, "", true}
|
||||
}
|
||||
if _, ok := args[0].(string); !ok {
|
||||
return nil, ArErr{"Import Error", "Invalid argument type", 0, realpath, "", true}
|
||||
}
|
||||
return importMod(args[0].(string), filepath.Dir(p), false)
|
||||
}},
|
||||
"cwd": ex,
|
||||
"exc": exc,
|
||||
"file": Map(anymap{
|
||||
"name": filepath.Base(p),
|
||||
"path": p,
|
||||
}),
|
||||
"main": main,
|
||||
"scope": global,
|
||||
}),
|
||||
})
|
||||
_, runimeErr, _ := run(translated, stack{vars, localvars, global})
|
||||
importing[p] = false
|
||||
if runimeErr.EXISTS {
|
||||
return nil, runimeErr
|
||||
return ArObject{}, runimeErr
|
||||
}
|
||||
imported[p] = global
|
||||
return global, ArErr{}
|
||||
}
|
||||
|
||||
40
src/json.go
40
src/json.go
@@ -11,17 +11,13 @@ import (
|
||||
func convertToArgon(obj any) any {
|
||||
switch x := obj.(type) {
|
||||
case map[string]interface{}:
|
||||
newmap := ArMap{}
|
||||
newmap := Map(anymap{})
|
||||
for key, value := range x {
|
||||
newmap[key] = convertToArgon(value)
|
||||
newmap.obj[key] = convertToArgon(value)
|
||||
}
|
||||
return newmap
|
||||
case ArArray:
|
||||
newarray := ArArray{}
|
||||
for _, value := range x {
|
||||
newarray = append(newarray, convertToArgon(value))
|
||||
}
|
||||
return newarray
|
||||
case []any:
|
||||
return ArArray(x)
|
||||
case string:
|
||||
return x
|
||||
case float64:
|
||||
@@ -47,8 +43,18 @@ func jsonstringify(obj any, level int) (string, error) {
|
||||
output := []string{}
|
||||
obj = classVal(obj)
|
||||
switch x := obj.(type) {
|
||||
case ArMap:
|
||||
for key, value := range x {
|
||||
case ArObject:
|
||||
if x.TYPE == "array" {
|
||||
for _, value := range x.obj["__value__"].([]any) {
|
||||
str, err := jsonstringify(value, level+1)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
output = append(output, str)
|
||||
}
|
||||
return "[" + strings.Join(output, ", ") + "]", nil
|
||||
}
|
||||
for key, value := range x.obj {
|
||||
str, err := jsonstringify(value, level+1)
|
||||
if err != nil {
|
||||
return "", err
|
||||
@@ -56,7 +62,7 @@ func jsonstringify(obj any, level int) (string, error) {
|
||||
output = append(output, ""+strconv.Quote(anyToArgon(key, false, true, 3, 0, false, 0))+": "+str)
|
||||
}
|
||||
return "{" + strings.Join(output, ", ") + "}", nil
|
||||
case ArArray:
|
||||
case []any:
|
||||
for _, value := range x {
|
||||
str, err := jsonstringify(value, level+1)
|
||||
if err != nil {
|
||||
@@ -82,24 +88,24 @@ func jsonstringify(obj any, level int) (string, error) {
|
||||
return "", err
|
||||
}
|
||||
|
||||
var ArJSON = ArMap{
|
||||
var ArJSON = Map(anymap{
|
||||
"parse": builtinFunc{"parse", func(args ...any) (any, ArErr) {
|
||||
if len(args) == 0 {
|
||||
return ArMap{}, ArErr{TYPE: "Runtime Error", message: "parse takes 1 argument", EXISTS: true}
|
||||
return nil, ArErr{TYPE: "Runtime Error", message: "parse takes 1 argument", EXISTS: true}
|
||||
}
|
||||
if typeof(args[0]) != "string" {
|
||||
return ArMap{}, ArErr{TYPE: "Runtime Error", message: "parse takes a string not a '" + typeof(args[0]) + "'", EXISTS: true}
|
||||
return nil, ArErr{TYPE: "Runtime Error", message: "parse takes a string not a '" + typeof(args[0]) + "'", EXISTS: true}
|
||||
}
|
||||
return jsonparse(args[0].(string)), ArErr{}
|
||||
}},
|
||||
"stringify": builtinFunc{"stringify", func(args ...any) (any, ArErr) {
|
||||
if len(args) == 0 {
|
||||
return ArMap{}, ArErr{TYPE: "Runtime Error", message: "stringify takes 1 argument", EXISTS: true}
|
||||
return nil, ArErr{TYPE: "Runtime Error", message: "stringify takes 1 argument", EXISTS: true}
|
||||
}
|
||||
str, err := jsonstringify(args[0], 0)
|
||||
if err != nil {
|
||||
return ArMap{}, ArErr{TYPE: "Runtime Error", message: err.Error(), EXISTS: true}
|
||||
return nil, ArErr{TYPE: "Runtime Error", message: err.Error(), EXISTS: true}
|
||||
}
|
||||
return str, ArErr{}
|
||||
}},
|
||||
}
|
||||
})
|
||||
|
||||
12
src/main.go
12
src/main.go
@@ -7,8 +7,14 @@ import (
|
||||
// args without the program path
|
||||
var Args = os.Args[1:]
|
||||
|
||||
type scope = ArMap
|
||||
type stack = []scope
|
||||
type stack = []ArObject
|
||||
|
||||
func newscope() ArObject {
|
||||
return ArObject{
|
||||
TYPE: "map",
|
||||
obj: make(anymap),
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
ex, e := os.Getwd()
|
||||
@@ -19,7 +25,7 @@ func main() {
|
||||
shell()
|
||||
os.Exit(0)
|
||||
}
|
||||
_, err := importMod(Args[0], ex)
|
||||
_, err := importMod(Args[0], ex, true)
|
||||
if err.EXISTS {
|
||||
panicErr(err)
|
||||
os.Exit(1)
|
||||
|
||||
8
src/map.go
Normal file
8
src/map.go
Normal file
@@ -0,0 +1,8 @@
|
||||
package main
|
||||
|
||||
func Map(val anymap) ArObject {
|
||||
return ArObject{
|
||||
TYPE: "map",
|
||||
obj: val,
|
||||
}
|
||||
}
|
||||
@@ -56,21 +56,30 @@ func runImport(importOBJ ArImport, stack stack, stacklevel int) (any, ArErr) {
|
||||
if e != nil {
|
||||
return nil, ArErr{"File Error", "could not get current working directory", importOBJ.line, importOBJ.path, importOBJ.code, true}
|
||||
}
|
||||
stackMap, err := importMod(path, ex)
|
||||
stackMap, err := importMod(path, ex, false)
|
||||
if err.EXISTS {
|
||||
if err.line == 0 {
|
||||
err.line = importOBJ.line
|
||||
}
|
||||
if err.path == "" {
|
||||
err.path = importOBJ.path
|
||||
}
|
||||
if err.code == "" {
|
||||
err.code = importOBJ.code
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
switch x := importOBJ.values.(type) {
|
||||
case []string:
|
||||
for _, v := range x {
|
||||
val, ok := stackMap[v]
|
||||
val, ok := stackMap.obj[v]
|
||||
if !ok {
|
||||
return nil, ArErr{"Import Error", "could not find value " + anyToArgon(v, true, false, 3, 0, false, 0) + " in module " + anyToArgon(path, true, false, 3, 0, false, 0), importOBJ.line, importOBJ.path, importOBJ.code, true}
|
||||
}
|
||||
stack[len(stack)-1][v] = val
|
||||
stack[len(stack)-1].obj[v] = val
|
||||
}
|
||||
case string:
|
||||
stack[len(stack)-1][x] = stackMap
|
||||
stack[len(stack)-1].obj[x] = stackMap
|
||||
}
|
||||
return nil, ArErr{}
|
||||
}
|
||||
|
||||
@@ -49,7 +49,7 @@ func randomRange(args ...any) (any, ArErr) {
|
||||
return rand, ArErr{}
|
||||
}
|
||||
|
||||
var ArRandom = ArMap{
|
||||
var ArRandom = Map(anymap{
|
||||
"__call__": builtinFunc{"random", func(args ...any) (any, ArErr) {
|
||||
if len(args) != 0 {
|
||||
return nil, ArErr{
|
||||
@@ -68,7 +68,7 @@ var ArRandom = ArMap{
|
||||
return round(resp.(number), 0), ArErr{}
|
||||
}},
|
||||
"range": builtinFunc{"range", randomRange},
|
||||
}
|
||||
})
|
||||
|
||||
func init() {
|
||||
rand.Seed(
|
||||
|
||||
@@ -7,7 +7,7 @@ import (
|
||||
)
|
||||
|
||||
func shell() {
|
||||
global := stack{vars, scope{}}
|
||||
global := stack{vars, newscope()}
|
||||
c := make(chan os.Signal, 1)
|
||||
signal.Notify(c, os.Interrupt)
|
||||
go func() {
|
||||
|
||||
@@ -5,9 +5,9 @@ import (
|
||||
"time"
|
||||
)
|
||||
|
||||
var timing = ArMap{}
|
||||
var timing = anymap{}
|
||||
|
||||
var plain = ArMap{
|
||||
var plain = Map(anymap{
|
||||
"log": builtinFunc{"log", func(args ...any) (any, ArErr) {
|
||||
output := []any{}
|
||||
for i := 0; i < len(args); i++ {
|
||||
@@ -32,9 +32,9 @@ var plain = ArMap{
|
||||
fmt.Println(output...)
|
||||
return nil, ArErr{}
|
||||
}},
|
||||
}
|
||||
})
|
||||
|
||||
var ArTerm = ArMap{
|
||||
var ArTerm = Map(anymap{
|
||||
"log": builtinFunc{"log", func(args ...any) (any, ArErr) {
|
||||
output := []any{}
|
||||
for i := 0; i < len(args); i++ {
|
||||
@@ -103,4 +103,4 @@ var ArTerm = ArMap{
|
||||
fmt.Printf("\x1b[%dm%s\x1b[0m", 34, fmt.Sprint(anyToArgon(id, false, true, 3, 0, false, 0), ": ", timesince)+"\n")
|
||||
return nil, ArErr{}
|
||||
}},
|
||||
}
|
||||
})
|
||||
|
||||
@@ -17,11 +17,11 @@ func ArThread(args ...any) (any, ArErr) {
|
||||
}
|
||||
var resp any
|
||||
var err ArErr
|
||||
currentscope := stack{vars, scope{}}
|
||||
currentscope := stack{vars, newscope()}
|
||||
hasrun := false
|
||||
joined := false
|
||||
var wg sync.WaitGroup
|
||||
threaMap := ArMap{
|
||||
threadMap := Map(anymap{
|
||||
"start": builtinFunc{"start", func(args ...any) (any, ArErr) {
|
||||
if hasrun {
|
||||
return nil, ArErr{TYPE: "Runtime Error", message: "Cannot start a thread twice", EXISTS: true}
|
||||
@@ -44,6 +44,6 @@ func ArThread(args ...any) (any, ArErr) {
|
||||
wg.Wait()
|
||||
return resp, err
|
||||
}},
|
||||
}
|
||||
return threaMap, ArErr{}
|
||||
})
|
||||
return threadMap, ArErr{}
|
||||
}
|
||||
|
||||
10
src/time.go
10
src/time.go
@@ -6,8 +6,8 @@ import (
|
||||
|
||||
var MicroSeconds = newNumber().SetInt64(1000000)
|
||||
|
||||
func ArTimeClass(N time.Time) ArMap {
|
||||
return ArMap{
|
||||
func ArTimeClass(N time.Time) ArObject {
|
||||
return Map(anymap{
|
||||
"__value__": newNumber().Quo(newNumber().SetInt64(N.UnixMicro()), MicroSeconds),
|
||||
"year": builtinFunc{
|
||||
"year",
|
||||
@@ -96,10 +96,10 @@ func ArTimeClass(N time.Time) ArMap {
|
||||
return N.Format(a[0].(string)), ArErr{}
|
||||
},
|
||||
},
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
var ArTime = map[any]any{
|
||||
var ArTime = Map(anymap{
|
||||
"snooze": builtinFunc{"snooze", func(a ...any) (any, ArErr) {
|
||||
if len(a) > 0 {
|
||||
float, _ := a[0].(number).Float64()
|
||||
@@ -212,4 +212,4 @@ var ArTime = map[any]any{
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
})
|
||||
|
||||
@@ -72,17 +72,17 @@ func anyToArgon(x any, quote bool, simplify bool, depth int, indent int, colored
|
||||
if colored {
|
||||
output = append(output, "\x1b[0m")
|
||||
}
|
||||
case ArMap:
|
||||
if _, ok := x["__value__"]; ok {
|
||||
return anyToArgon(x["__value__"], quote, simplify, depth, indent, colored, plain)
|
||||
case ArObject:
|
||||
if x.TYPE == "array" {
|
||||
return anyToArgon(x.obj["__value__"], quote, simplify, depth, indent, colored, plain)
|
||||
}
|
||||
if len(x) == 0 {
|
||||
if len(x.obj) == 0 {
|
||||
return "{}"
|
||||
}
|
||||
keys := make([]any, len(x))
|
||||
keys := make([]any, len(x.obj))
|
||||
|
||||
i := 0
|
||||
for k := range x {
|
||||
for k := range x.obj {
|
||||
keys[i] = k
|
||||
i++
|
||||
}
|
||||
@@ -103,13 +103,11 @@ func anyToArgon(x any, quote bool, simplify bool, depth int, indent int, colored
|
||||
}
|
||||
keyval = strings.Join(outputkeyval, "")
|
||||
}
|
||||
output = append(output, keyval+": "+anyToArgon(x[key], true, true, depth-1, indent+1, colored, plain))
|
||||
output = append(output, keyval+": "+anyToArgon(x.obj[key], true, true, depth-1, indent+1, colored, plain))
|
||||
}
|
||||
return "{" + maybenewline + (strings.Repeat(" ", (indent+1)*plain)) + strings.Join(output, ","+maybenewline+(strings.Repeat(" ", (indent+1)*plain))) + maybenewline + (strings.Repeat(" ", indent*plain)) + "}"
|
||||
case ArArray:
|
||||
if len(x) == 0 {
|
||||
return "[]"
|
||||
}
|
||||
case []any:
|
||||
singleline := len(x) <= 3
|
||||
output := []string{}
|
||||
if simplify && len(x) >= 100 {
|
||||
for i := 0; i < 10; i++ {
|
||||
@@ -128,9 +126,17 @@ func anyToArgon(x any, quote bool, simplify bool, depth int, indent int, colored
|
||||
} else {
|
||||
for i := 0; i < len(x); i++ {
|
||||
item := x[i]
|
||||
output = append(output, anyToArgon(item, true, true, depth-1, indent+1, colored, plain))
|
||||
converted := anyToArgon(item, true, true, depth-1, indent+1, colored, plain)
|
||||
if singleline && strings.Contains(converted, "\n") {
|
||||
singleline = false
|
||||
}
|
||||
output = append(output, converted)
|
||||
}
|
||||
}
|
||||
|
||||
if singleline {
|
||||
return "[" + strings.Join(output, ", ") + "]"
|
||||
}
|
||||
return "[" + maybenewline + (strings.Repeat(" ", (indent+1)*plain)) + strings.Join(output, ","+maybenewline+(strings.Repeat(" ", (indent+1)*plain))) + maybenewline + (strings.Repeat(" ", indent*plain)) + "]"
|
||||
case builtinFunc:
|
||||
if colored {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package main
|
||||
|
||||
func typeof(val any) string {
|
||||
switch val.(type) {
|
||||
switch x := val.(type) {
|
||||
case number:
|
||||
return "number"
|
||||
case string:
|
||||
@@ -14,10 +14,11 @@ func typeof(val any) string {
|
||||
return "function"
|
||||
case builtinFunc:
|
||||
return "function"
|
||||
case ArMap:
|
||||
case ArObject:
|
||||
if x.TYPE == "array" {
|
||||
return "array"
|
||||
}
|
||||
return "map"
|
||||
case ArArray:
|
||||
return "array"
|
||||
case accessVariable:
|
||||
return "variable"
|
||||
}
|
||||
|
||||
@@ -78,7 +78,7 @@ func parseVariable(code UNPARSEcode) (accessVariable, bool, ArErr, int) {
|
||||
func readVariable(v accessVariable, stack stack) (any, ArErr) {
|
||||
for i := len(stack) - 1; i >= 0; i-- {
|
||||
varMutex.RLock()
|
||||
val, ok := stack[i][v.name]
|
||||
val, ok := stack[i].obj[v.name]
|
||||
varMutex.RUnlock()
|
||||
if ok {
|
||||
return val, ArErr{}
|
||||
@@ -208,30 +208,30 @@ func setVariableValue(v setVariable, stack stack, stacklevel int) (any, ArErr) {
|
||||
|
||||
if v.TYPE == "let" {
|
||||
varMutex.RLock()
|
||||
_, ok := stack[len(stack)-1][v.toset.(accessVariable).name]
|
||||
_, ok := stack[len(stack)-1].obj[v.toset.(accessVariable).name]
|
||||
varMutex.RUnlock()
|
||||
if ok {
|
||||
return nil, ArErr{"Runtime Error", "variable \"" + v.toset.(accessVariable).name + "\" already exists", v.line, v.path, v.code, true}
|
||||
}
|
||||
varMutex.Lock()
|
||||
stack[len(stack)-1][v.toset.(accessVariable).name] = resp
|
||||
stack[len(stack)-1].obj[v.toset.(accessVariable).name] = resp
|
||||
varMutex.Unlock()
|
||||
} else {
|
||||
switch x := v.toset.(type) {
|
||||
case accessVariable:
|
||||
for i := len(stack) - 1; i >= 0; i-- {
|
||||
varMutex.RLock()
|
||||
_, ok := stack[i][x.name]
|
||||
_, ok := stack[i].obj[x.name]
|
||||
varMutex.RUnlock()
|
||||
if ok {
|
||||
varMutex.Lock()
|
||||
stack[i][x.name] = resp
|
||||
stack[i].obj[x.name] = resp
|
||||
varMutex.Unlock()
|
||||
return ThrowOnNonLoop(resp, ArErr{})
|
||||
}
|
||||
}
|
||||
varMutex.Lock()
|
||||
stack[len(stack)-1][x.name] = resp
|
||||
stack[len(stack)-1].obj[x.name] = resp
|
||||
varMutex.Unlock()
|
||||
case ArMapGet:
|
||||
respp, err := runVal(x.VAL, stack, stacklevel+1)
|
||||
@@ -246,12 +246,12 @@ func setVariableValue(v setVariable, stack stack, stacklevel int) (any, ArErr) {
|
||||
return nil, err
|
||||
}
|
||||
switch y := respp.(type) {
|
||||
case ArMap:
|
||||
case ArObject:
|
||||
if isUnhashable(key) {
|
||||
return nil, ArErr{"Runtime Error", "can't use unhashable type as map key: " + typeof(key), v.line, v.path, v.code, true}
|
||||
}
|
||||
varMutex.Lock()
|
||||
y[key] = resp
|
||||
y.obj[key] = resp
|
||||
varMutex.Unlock()
|
||||
default:
|
||||
return nil, ArErr{"Runtime Error", "can't set for non map", v.line, v.path, v.code, true}
|
||||
@@ -285,8 +285,8 @@ func runDelete(d ArDelete, stack stack, stacklevel int) (any, ArErr) {
|
||||
switch x := d.value.(type) {
|
||||
case accessVariable:
|
||||
for i := len(stack) - 1; i >= 0; i-- {
|
||||
if _, ok := stack[i][x.name]; ok {
|
||||
delete(stack[i], x.name)
|
||||
if _, ok := stack[i].obj[x.name]; ok {
|
||||
delete(stack[i].obj, x.name)
|
||||
return nil, ArErr{}
|
||||
}
|
||||
}
|
||||
@@ -304,8 +304,14 @@ func runDelete(d ArDelete, stack stack, stacklevel int) (any, ArErr) {
|
||||
return nil, err
|
||||
}
|
||||
switch y := respp.(type) {
|
||||
case ArMap:
|
||||
delete(y, key)
|
||||
case ArObject:
|
||||
if y.TYPE == "array" {
|
||||
return nil, ArErr{"Runtime Error", "can't delete from array", d.line, d.path, d.code, true}
|
||||
}
|
||||
if isUnhashable(key) {
|
||||
return nil, ArErr{"Runtime Error", "can't use unhashable type as map key: " + typeof(key), d.line, d.path, d.code, true}
|
||||
}
|
||||
delete(y.obj, key)
|
||||
default:
|
||||
return nil, ArErr{"Runtime Error", "can't delete for non map", d.line, d.path, d.code, true}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user