make arrays an object

This commit is contained in:
2023-03-15 21:02:00 +00:00
parent b53f2b4a0a
commit 814209c392
24 changed files with 545 additions and 325 deletions

View File

@@ -1,8 +1,5 @@
i = 0 x = map()
output = [] x.poo = 10
while (i < 1000) do y = [x,x,x]
output = append(output, i) term.log(y)
i = i + 1
file.write('output.json').json(output)

View File

@@ -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
]

View File

@@ -5,7 +5,7 @@ import "strings"
var arrayCompile = makeRegex(`( *)\[(.|\n)*\]( *)`) var arrayCompile = makeRegex(`( *)\[(.|\n)*\]( *)`)
type CreateArray struct { type CreateArray struct {
value ArArray value []any
line int line int
code string code string
path string path string
@@ -15,6 +15,233 @@ func isArray(code UNPARSEcode) bool {
return arrayCompile.MatchString(code.code) 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) { func parseArray(code UNPARSEcode, index int, codelines []UNPARSEcode) (any, bool, ArErr, int) {
trimmed := strings.TrimSpace(code.code) trimmed := strings.TrimSpace(code.code)
trimmed = trimmed[1 : len(trimmed)-1] trimmed = trimmed[1 : len(trimmed)-1]
@@ -27,14 +254,14 @@ func parseArray(code UNPARSEcode, index int, codelines []UNPARSEcode) (any, bool
}, worked, err, 1 }, worked, err, 1
} }
func runArray(a CreateArray, stack stack, stacklevel int) ([]any, ArErr) { func runArray(a CreateArray, stack stack, stacklevel int) (ArObject, ArErr) {
var array ArArray var array []any
for _, val := range a.value { for _, val := range a.value {
val, err := runVal(val, stack, stacklevel+1) val, err := runVal(val, stack, stacklevel+1)
if err.EXISTS { if err.EXISTS {
return nil, err return ArObject{}, err
} }
array = append(array, val) array = append(array, val)
} }
return array, ArErr{} return ArArray(array), ArErr{}
} }

View File

@@ -12,8 +12,11 @@ func anyToBool(x any) bool {
return x return x
case nil: case nil:
return false return false
case ArMap: case ArObject:
return len(x) != 0 if x.TYPE == "array" {
return len(x.obj["__value__"].([]any)) != 0
}
return len(x.obj) != 0
case builtinFunc: case builtinFunc:
return true return true
case Callable: case Callable:

View File

@@ -1,97 +1,97 @@
package main package main
import ( var vars = Map(anymap{})
"fmt"
"strings"
)
var vars = scope{}
func init() { func init() {
vars["global"] = vars vars.obj["global"] = vars
vars["term"] = ArTerm vars.obj["term"] = ArTerm
vars["input"] = builtinFunc{"input", ArgonInput} vars.obj["input"] = builtinFunc{"input", ArgonInput}
vars["number"] = builtinFunc{"number", ArgonNumber} vars.obj["number"] = builtinFunc{"number", ArgonNumber}
vars["string"] = builtinFunc{"string", ArgonString} vars.obj["string"] = builtinFunc{"string", ArgonString}
vars["infinity"] = infinity vars.obj["infinity"] = infinity
vars["length"] = builtinFunc{"length", func(a ...any) (any, ArErr) { vars.obj["length"] = builtinFunc{"length", func(a ...any) (any, ArErr) {
switch x := a[0].(type) { switch x := a[0].(type) {
case string: case string:
return len(x), ArErr{} return len(x), ArErr{}
case ArMap: case ArObject:
return len(x), ArErr{} 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} 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 { if len(a) == 0 {
return ArMap{}, ArErr{} return Map(anymap{}), ArErr{}
} }
switch x := a[0].(type) { 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{} return x, ArErr{}
case string: case string:
newmap := ArMap{} newmap := anymap{}
for i, v := range x { for i, v := range x {
newmap[i] = string(v) newmap[i] = string(v)
} }
return newmap, ArErr{} return Map(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 nil, ArErr{TYPE: "TypeError", message: "Cannot create map from '" + typeof(a[0]) + "'", EXISTS: true} 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 { if len(a) == 0 {
return ArArray{}, ArErr{} return ArArray([]any{}), ArErr{}
} }
switch x := a[0].(type) { switch x := a[0].(type) {
case ArArray:
return x, ArErr{}
case string: case string:
newarray := ArArray{} newarray := []any{}
for _, v := range x { for _, v := range x {
newarray = append(newarray, string(v)) newarray = append(newarray, string(v))
} }
return newarray, ArErr{} return ArArray(newarray), ArErr{}
case ArMap: case ArObject:
newarray := ArArray{} if x.TYPE == "array" {
for key, val := range x { return x, ArErr{}
newarray = append(newarray, ArArray{key, val})
} }
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} 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 { if len(a) == 0 {
return false, ArErr{} return false, ArErr{}
} }
return anyToBool(a[0]), ArErr{} return anyToBool(a[0]), ArErr{}
}} }}
vars["time"] = ArTime vars.obj["time"] = ArTime
vars["PI"] = PI vars.obj["PI"] = PI
vars["π"] = PI vars.obj["π"] = PI
vars["e"] = e vars.obj["e"] = e
vars["ln"] = builtinFunc{"ln", ArgonLn} vars.obj["ln"] = builtinFunc{"ln", ArgonLn}
vars["log"] = builtinFunc{"log", ArgonLog} vars.obj["log"] = builtinFunc{"log", ArgonLog}
vars["logN"] = builtinFunc{"logN", ArgonLogN} vars.obj["logN"] = builtinFunc{"logN", ArgonLogN}
vars["thread"] = builtinFunc{"thread", ArThread} vars.obj["thread"] = builtinFunc{"thread", ArThread}
vars["round"] = builtinFunc{"round", func(a ...any) (any, ArErr) { vars.obj["round"] = builtinFunc{"round", func(a ...any) (any, ArErr) {
if len(a) == 0 { if len(a) == 0 {
return nil, ArErr{TYPE: "round", message: "round takes 1 argument", return nil, ArErr{TYPE: "round", message: "round takes 1 argument",
EXISTS: true} EXISTS: true}
@@ -115,7 +115,7 @@ func init() {
} }
return nil, ArErr{TYPE: "TypeError", message: "Cannot round '" + typeof(a[0]) + "'", EXISTS: true} 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 { if len(a) == 0 {
return nil, ArErr{TYPE: "floor", message: "floor takes 1 argument", return nil, ArErr{TYPE: "floor", message: "floor takes 1 argument",
EXISTS: true} EXISTS: true}
@@ -126,7 +126,7 @@ func init() {
} }
return nil, ArErr{TYPE: "TypeError", message: "Cannot floor '" + typeof(a[0]) + "'", EXISTS: true} 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 { if len(a) == 0 {
return nil, ArErr{TYPE: "ceil", message: "ceil takes 1 argument", return nil, ArErr{TYPE: "ceil", message: "ceil takes 1 argument",
EXISTS: true} EXISTS: true}
@@ -138,36 +138,10 @@ func init() {
} }
return nil, ArErr{TYPE: "TypeError", message: "Cannot ceil '" + typeof(a[0]) + "'", EXISTS: true} return nil, ArErr{TYPE: "TypeError", message: "Cannot ceil '" + typeof(a[0]) + "'", EXISTS: true}
}} }}
vars["append"] = builtinFunc{"append", func(a ...any) (any, ArErr) { vars.obj["sqrt"] = builtinFunc{"sqrt", ArgonSqrt}
if len(a) != 2 { vars.obj["file"] = ArFile
return nil, ArErr{TYPE: "append", message: "append takes 2 arguments, got " + fmt.Sprint(len(a)), vars.obj["random"] = ArRandom
EXISTS: true} vars.obj["json"] = ArJSON
} vars.obj["sin"] = ArSin
switch x := a[0].(type) { vars.obj["arcsin"] = ArArcsin
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
} }

View File

@@ -15,6 +15,14 @@ type call struct {
path string path string
} }
type Callable struct {
params []string
run any
code string
stack stack
line int
}
func isCall(code UNPARSEcode) bool { func isCall(code UNPARSEcode) bool {
return callCompile.MatchString(code.code) 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++ { for i := 1; i < len(splitby); i++ {
name := strings.Join(splitby[0:i], "(") name := strings.Join(splitby[0:i], "(")
argstr := strings.Join(splitby[i:], "(") argstr := strings.Join(splitby[i:], "(")
args, success, argserr := getValuesFromLetter(argstr, ",", index, codelines, true) args, success, argserr := getValuesFromLetter(argstr, ",", index, codelines, false)
arguments = args arguments = args
if !success { if !success {
if i == len(splitby)-1 { if i == len(splitby)-1 {
@@ -68,13 +76,13 @@ func runCall(c call, stack stack, stacklevel int) (any, ArErr) {
return nil, err return nil, err
} }
switch x := callable_.(type) { switch x := callable_.(type) {
case ArMap: case ArObject:
callable_ = x["__call__"] callable_ = x.obj["__call__"]
} }
callable = callable_ callable = callable_
} }
args := []any{} args := []any{}
level := append(stack, scope{}) level := append(stack, newscope())
for _, arg := range c.args { for _, arg := range c.args {
resp, err := runVal(arg, level, stacklevel+1) resp, err := runVal(arg, level, stacklevel+1)
if err.EXISTS { if err.EXISTS {
@@ -101,9 +109,9 @@ func runCall(c call, stack stack, stacklevel int) (any, ArErr) {
if len(x.params) != len(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} 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 { 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) resp, err := runVal(x.run, append(x.stack, level), stacklevel+1)
return ThrowOnNonLoop(openReturn(resp), err) return ThrowOnNonLoop(openReturn(resp), err)

View File

@@ -1,9 +0,0 @@
package main
type Callable struct {
params []string
run any
code string
stack stack
line int
}

View File

@@ -49,7 +49,7 @@ func parseDoWrap(code UNPARSEcode, index int, codelines []UNPARSEcode) (any, boo
} }
func runDoWrap(d dowrap, stack stack, stacklevel int) (any, ArErr) { func runDoWrap(d dowrap, stack stack, stacklevel int) (any, ArErr) {
newstack := append(stack, scope{}) newstack := append(stack, newscope())
for _, v := range d.run { for _, v := range d.run {
val, err := runVal(v, newstack, stacklevel+1) val, err := runVal(v, newstack, stacklevel+1)
if err.EXISTS { if err.EXISTS {

View File

@@ -7,10 +7,10 @@ import (
"os" "os"
) )
var ArFile = ArMap{ var ArFile = Map(anymap{
"read": builtinFunc{"read", ArRead}, "read": builtinFunc{"read", ArRead},
"write": builtinFunc{"write", ArWrite}, "write": builtinFunc{"write", ArWrite},
} })
func readtext(file *os.File) (string, error) { func readtext(file *os.File) (string, error) {
var buf bytes.Buffer var buf bytes.Buffer
@@ -23,68 +23,68 @@ func readtext(file *os.File) (string, error) {
func ArRead(args ...any) (any, ArErr) { func ArRead(args ...any) (any, ArErr) {
if len(args) != 1 { 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" { 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) filename := args[0].(string)
file, err := os.Open(filename) file, err := os.Open(filename)
if err != nil { 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": builtinFunc{"text", func(...any) (any, ArErr) {
text, err := readtext(file) text, err := readtext(file)
if err != nil { 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{} return text, ArErr{}
}}, }},
"json": builtinFunc{"json", func(...any) (any, ArErr) { "json": builtinFunc{"json", func(...any) (any, ArErr) {
text, err := readtext(file) text, err := readtext(file)
if err != nil { 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{} return jsonparse(text), ArErr{}
}}, }},
}, ArErr{} }), ArErr{}
} }
func ArWrite(args ...any) (any, ArErr) { func ArWrite(args ...any) (any, ArErr) {
if len(args) != 1 { 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" { 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) filename := args[0].(string)
file, err := os.Create(filename) file, err := os.Create(filename)
if err != nil { 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) { "text": builtinFunc{"text", func(args ...any) (any, ArErr) {
if len(args) != 1 { 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" { 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))) file.Write([]byte(args[0].(string)))
return nil, ArErr{} return nil, ArErr{}
}}, }},
"json": builtinFunc{"json", func(args ...any) (any, ArErr) { "json": builtinFunc{"json", func(args ...any) (any, ArErr) {
if len(args) != 1 { 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) jsonstr, err := jsonstringify(args[0], 0)
if err != nil { 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)) file.Write([]byte(jsonstr))
return nil, ArErr{} return nil, ArErr{}
}}, }},
}, ArErr{} }), ArErr{}
} }

View File

@@ -5,15 +5,19 @@ import (
"strings" "strings"
) )
type ArMap = map[any]any type ArObject struct {
type ArArray = []any 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 mapGetCompile = makeRegex(`(.|\n)+\.([a-zA-Z_]|(\p{L}\p{M}*))([a-zA-Z0-9_]|(\p{L}\p{M}*))*( *)`)
var indexGetCompile = makeRegex(`(.|\n)+\[(.|\n)+\]( *)`) var indexGetCompile = makeRegex(`(.|\n)+\[(.|\n)+\]( *)`)
type ArMapGet struct { type ArMapGet struct {
VAL any VAL any
args ArArray args []any
index bool index bool
line int line int
code string code string
@@ -26,7 +30,14 @@ func mapGet(r ArMapGet, stack stack, stacklevel int) (any, ArErr) {
return nil, err return nil, err
} }
switch m := resp.(type) { 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 { if len(r.args) > 1 {
return nil, ArErr{ return nil, ArErr{
"IndexError", "IndexError",
@@ -51,7 +62,7 @@ func mapGet(r ArMapGet, stack stack, stacklevel int) (any, ArErr) {
true, true,
} }
} }
if _, ok := m[key]; !ok { if _, ok := m.obj[key]; !ok {
return nil, ArErr{ return nil, ArErr{
"KeyError", "KeyError",
"key '" + fmt.Sprint(key) + "' not found", "key '" + fmt.Sprint(key) + "' not found",
@@ -61,12 +72,15 @@ func mapGet(r ArMapGet, stack stack, stacklevel int) (any, ArErr) {
true, true,
} }
} }
return m[key], ArErr{} return potentialAnyArrayToArArray(m.obj[key]), ArErr{}
case ArArray:
return getFromArArray(m, r, stack, stacklevel)
case string: 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) 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 { func classVal(r any) any {
if _, ok := r.(ArMap); ok { if j, ok := r.(ArObject); ok {
if _, ok := r.(ArMap)["__value__"]; ok { if _, ok := j.obj["__value__"]; ok {
return r.(ArMap)["__value__"] return j.obj["__value__"]
} }
} }
return r return r
@@ -105,7 +119,7 @@ func mapGetParse(code UNPARSEcode, index int, codelines []UNPARSEcode) (ArMapGet
if !worked { if !worked {
return ArMapGet{}, false, err, i 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 { func isIndexGet(code UNPARSEcode) bool {
@@ -126,7 +140,6 @@ func indexGetParse(code UNPARSEcode, index int, codelines []UNPARSEcode) (ArMapG
} }
continue continue
} }
fmt.Println(args)
if len(args) > 3 { if len(args) > 3 {
return ArMapGet{}, false, ArErr{ return ArMapGet{}, false, ArErr{
"SyntaxError", "SyntaxError",
@@ -161,7 +174,7 @@ func isUnhashable(val any) bool {
return keytype == "array" || keytype == "map" 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 ( var (
start int = 0 start int = 0
end any = nil 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) startval, err := runVal(r.args[0], stack, stacklevel+1)
if err.EXISTS { if err.EXISTS {
return nil, err return ArObject{}, err
} }
if startval == nil { if startval == nil {
start = 0 start = 0
} else if typeof(startval) != "number" && !startval.(number).IsInt() { } else if typeof(startval) != "number" || !startval.(number).IsInt() {
return nil, ArErr{ return ArObject{}, ArErr{
"TypeError", "TypeError",
"slice index must be an integer", "slice index must be an integer",
r.line, r.line,
@@ -190,12 +203,12 @@ func getFromArArray(m []any, r ArMapGet, stack stack, stacklevel int) (ArArray,
if len(r.args) > 1 { if len(r.args) > 1 {
endval, err := runVal(r.args[1], stack, stacklevel+1) endval, err := runVal(r.args[1], stack, stacklevel+1)
if err.EXISTS { if err.EXISTS {
return nil, err return ArObject{}, err
} }
if endval == nil { if endval == nil {
end = len(m) end = m.obj["length"]
} else if typeof(endval) != "number" && !endval.(number).IsInt() { } else if typeof(endval) != "number" && !endval.(number).IsInt() {
return nil, ArErr{ return ArObject{}, ArErr{
"TypeError", "TypeError",
"slice ending index must be an integer", "slice ending index must be an integer",
r.line, r.line,
@@ -210,12 +223,12 @@ func getFromArArray(m []any, r ArMapGet, stack stack, stacklevel int) (ArArray,
if len(r.args) > 2 { if len(r.args) > 2 {
stepval, err := runVal(r.args[2], stack, stacklevel+1) stepval, err := runVal(r.args[2], stack, stacklevel+1)
if err.EXISTS { if err.EXISTS {
return nil, err return ArObject{}, err
} }
if stepval == nil { if stepval == nil {
step = 1 step = 1
} else if typeof(stepval) != "number" && !stepval.(number).IsInt() { } else if typeof(stepval) != "number" && !stepval.(number).IsInt() {
return nil, ArErr{ return ArObject{}, ArErr{
"TypeError", "TypeError",
"slice step must be an integer", "slice step must be an integer",
r.line, r.line,
@@ -228,29 +241,27 @@ func getFromArArray(m []any, r ArMapGet, stack stack, stacklevel int) (ArArray,
} }
} }
if start < 0 { if start < 0 {
start = len(m) + start start = m.obj["length"].(int) + start
} }
if _, ok := end.(int); ok && end.(int) < 0 { 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 { if end == nil {
return ArArray{m[start]}, ArErr{} return ArArray([]any{m.obj["__value__"].([]any)[start]}), ArErr{}
} else if step == 1 { } else if step == 1 {
return m[start:end.(int)], ArErr{} return ArArray([]any{m.obj["__value__"].([]any)[start:end.(int)]}), ArErr{}
} else { } else {
output := ArArray{} output := []any{}
if step > 0 { if step > 0 {
for i := start; i < end.(int); i += step { for i := start; i < end.(int); i += step {
output = append(output, m[i]) output = append(output, m.obj["__value__"].([]any)[i])
} }
} else { } else {
for i := end.(int) - 1; i >= start; i += step { 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 { if startval == nil {
start = 0 start = 0
} else if typeof(startval) != "number" && !startval.(number).IsInt() { } else if typeof(startval) != "number" || !startval.(number).IsInt() {
return "", ArErr{ return "", ArErr{
"TypeError", "TypeError",
"slice index must be an integer", "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 { if _, ok := end.(int); ok && end.(int) < 0 {
end = len(m) + end.(int) end = len(m) + end.(int)
} }
fmt.Println(start, end, step)
if end == nil { if end == nil {
return string(m[start]), ArErr{} return string(m[start]), ArErr{}
} else if step == 1 { } else if step == 1 {

View File

@@ -118,7 +118,7 @@ func parseIfStatement(code UNPARSEcode, index int, codeline []UNPARSEcode) (ifst
func runIfStatement(code ifstatement, stack stack, stacklevel int) (any, ArErr) { func runIfStatement(code ifstatement, stack stack, stacklevel int) (any, ArErr) {
for _, condition := range code.conditions { for _, condition := range code.conditions {
newstack := append(stack, scope{}) newstack := append(stack, newscope())
resp, err := runVal(condition.condition, newstack, stacklevel+1) resp, err := runVal(condition.condition, newstack, stacklevel+1)
if err.EXISTS { if err.EXISTS {
return nil, err return nil, err
@@ -128,7 +128,7 @@ func runIfStatement(code ifstatement, stack stack, stacklevel int) (any, ArErr)
} }
} }
if code.ELSE != nil { 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{} return nil, ArErr{}
} }

View File

@@ -8,6 +8,9 @@ import (
"path/filepath" "path/filepath"
) )
var imported = make(map[string]ArObject)
var importing = make(map[string]bool)
func FileExists(filename string) bool { func FileExists(filename string) bool {
if _, err := os.Stat(filename); err == nil { if _, err := os.Stat(filename); err == nil {
return true return true
@@ -44,7 +47,7 @@ func readFile(path string) []UNPARSEcode {
return output return output
} }
func importMod(realpath string, origin string) (scope, ArErr) { func importMod(realpath string, origin string, main bool) (ArObject, ArErr) {
extention := filepath.Ext(realpath) extention := filepath.Ext(realpath)
path := realpath path := realpath
if extention == "" { if extention == "" {
@@ -52,13 +55,13 @@ func importMod(realpath string, origin string) (scope, ArErr) {
} }
ex, err := os.Getwd() ex, err := os.Getwd()
if err != nil { 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 { 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) isABS := filepath.IsAbs(path)
var pathsToTest []string var pathsToTest []string
if isABS { if isABS {
@@ -90,18 +93,52 @@ func importMod(realpath string, origin string) (scope, ArErr) {
} }
if !found { 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) codelines := readFile(p)
translated, translationerr := translate(codelines) translated, translationerr := translate(codelines)
if translationerr.EXISTS { if translationerr.EXISTS {
return nil, translationerr return ArObject{}, translationerr
} }
global := scope{} ArgsArArray := []any{}
_, runimeErr, _ := run(translated, stack{vars, global}) 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 { if runimeErr.EXISTS {
return nil, runimeErr return ArObject{}, runimeErr
} }
imported[p] = global
return global, ArErr{} return global, ArErr{}
} }

View File

@@ -11,17 +11,13 @@ import (
func convertToArgon(obj any) any { func convertToArgon(obj any) any {
switch x := obj.(type) { switch x := obj.(type) {
case map[string]interface{}: case map[string]interface{}:
newmap := ArMap{} newmap := Map(anymap{})
for key, value := range x { for key, value := range x {
newmap[key] = convertToArgon(value) newmap.obj[key] = convertToArgon(value)
} }
return newmap return newmap
case ArArray: case []any:
newarray := ArArray{} return ArArray(x)
for _, value := range x {
newarray = append(newarray, convertToArgon(value))
}
return newarray
case string: case string:
return x return x
case float64: case float64:
@@ -47,8 +43,18 @@ func jsonstringify(obj any, level int) (string, error) {
output := []string{} output := []string{}
obj = classVal(obj) obj = classVal(obj)
switch x := obj.(type) { switch x := obj.(type) {
case ArMap: case ArObject:
for key, value := range x { 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) str, err := jsonstringify(value, level+1)
if err != nil { if err != nil {
return "", err 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) output = append(output, ""+strconv.Quote(anyToArgon(key, false, true, 3, 0, false, 0))+": "+str)
} }
return "{" + strings.Join(output, ", ") + "}", nil return "{" + strings.Join(output, ", ") + "}", nil
case ArArray: case []any:
for _, value := range x { for _, value := range x {
str, err := jsonstringify(value, level+1) str, err := jsonstringify(value, level+1)
if err != nil { if err != nil {
@@ -82,24 +88,24 @@ func jsonstringify(obj any, level int) (string, error) {
return "", err return "", err
} }
var ArJSON = ArMap{ var ArJSON = Map(anymap{
"parse": builtinFunc{"parse", func(args ...any) (any, ArErr) { "parse": builtinFunc{"parse", func(args ...any) (any, ArErr) {
if len(args) == 0 { 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" { 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{} return jsonparse(args[0].(string)), ArErr{}
}}, }},
"stringify": builtinFunc{"stringify", func(args ...any) (any, ArErr) { "stringify": builtinFunc{"stringify", func(args ...any) (any, ArErr) {
if len(args) == 0 { 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) str, err := jsonstringify(args[0], 0)
if err != nil { 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{} return str, ArErr{}
}}, }},
} })

View File

@@ -7,8 +7,14 @@ import (
// args without the program path // args without the program path
var Args = os.Args[1:] var Args = os.Args[1:]
type scope = ArMap type stack = []ArObject
type stack = []scope
func newscope() ArObject {
return ArObject{
TYPE: "map",
obj: make(anymap),
}
}
func main() { func main() {
ex, e := os.Getwd() ex, e := os.Getwd()
@@ -19,7 +25,7 @@ func main() {
shell() shell()
os.Exit(0) os.Exit(0)
} }
_, err := importMod(Args[0], ex) _, err := importMod(Args[0], ex, true)
if err.EXISTS { if err.EXISTS {
panicErr(err) panicErr(err)
os.Exit(1) os.Exit(1)

8
src/map.go Normal file
View File

@@ -0,0 +1,8 @@
package main
func Map(val anymap) ArObject {
return ArObject{
TYPE: "map",
obj: val,
}
}

View File

@@ -56,21 +56,30 @@ func runImport(importOBJ ArImport, stack stack, stacklevel int) (any, ArErr) {
if e != nil { if e != nil {
return nil, ArErr{"File Error", "could not get current working directory", importOBJ.line, importOBJ.path, importOBJ.code, true} 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.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 return nil, err
} }
switch x := importOBJ.values.(type) { switch x := importOBJ.values.(type) {
case []string: case []string:
for _, v := range x { for _, v := range x {
val, ok := stackMap[v] val, ok := stackMap.obj[v]
if !ok { 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} 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: case string:
stack[len(stack)-1][x] = stackMap stack[len(stack)-1].obj[x] = stackMap
} }
return nil, ArErr{} return nil, ArErr{}
} }

View File

@@ -49,7 +49,7 @@ func randomRange(args ...any) (any, ArErr) {
return rand, ArErr{} return rand, ArErr{}
} }
var ArRandom = ArMap{ var ArRandom = Map(anymap{
"__call__": builtinFunc{"random", func(args ...any) (any, ArErr) { "__call__": builtinFunc{"random", func(args ...any) (any, ArErr) {
if len(args) != 0 { if len(args) != 0 {
return nil, ArErr{ return nil, ArErr{
@@ -68,7 +68,7 @@ var ArRandom = ArMap{
return round(resp.(number), 0), ArErr{} return round(resp.(number), 0), ArErr{}
}}, }},
"range": builtinFunc{"range", randomRange}, "range": builtinFunc{"range", randomRange},
} })
func init() { func init() {
rand.Seed( rand.Seed(

View File

@@ -7,7 +7,7 @@ import (
) )
func shell() { func shell() {
global := stack{vars, scope{}} global := stack{vars, newscope()}
c := make(chan os.Signal, 1) c := make(chan os.Signal, 1)
signal.Notify(c, os.Interrupt) signal.Notify(c, os.Interrupt)
go func() { go func() {

View File

@@ -5,9 +5,9 @@ import (
"time" "time"
) )
var timing = ArMap{} var timing = anymap{}
var plain = ArMap{ var plain = Map(anymap{
"log": builtinFunc{"log", func(args ...any) (any, ArErr) { "log": builtinFunc{"log", func(args ...any) (any, ArErr) {
output := []any{} output := []any{}
for i := 0; i < len(args); i++ { for i := 0; i < len(args); i++ {
@@ -32,9 +32,9 @@ var plain = ArMap{
fmt.Println(output...) fmt.Println(output...)
return nil, ArErr{} return nil, ArErr{}
}}, }},
} })
var ArTerm = ArMap{ var ArTerm = Map(anymap{
"log": builtinFunc{"log", func(args ...any) (any, ArErr) { "log": builtinFunc{"log", func(args ...any) (any, ArErr) {
output := []any{} output := []any{}
for i := 0; i < len(args); i++ { 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") fmt.Printf("\x1b[%dm%s\x1b[0m", 34, fmt.Sprint(anyToArgon(id, false, true, 3, 0, false, 0), ": ", timesince)+"\n")
return nil, ArErr{} return nil, ArErr{}
}}, }},
} })

View File

@@ -17,11 +17,11 @@ func ArThread(args ...any) (any, ArErr) {
} }
var resp any var resp any
var err ArErr var err ArErr
currentscope := stack{vars, scope{}} currentscope := stack{vars, newscope()}
hasrun := false hasrun := false
joined := false joined := false
var wg sync.WaitGroup var wg sync.WaitGroup
threaMap := ArMap{ threadMap := Map(anymap{
"start": builtinFunc{"start", func(args ...any) (any, ArErr) { "start": builtinFunc{"start", func(args ...any) (any, ArErr) {
if hasrun { if hasrun {
return nil, ArErr{TYPE: "Runtime Error", message: "Cannot start a thread twice", EXISTS: true} 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() wg.Wait()
return resp, err return resp, err
}}, }},
} })
return threaMap, ArErr{} return threadMap, ArErr{}
} }

View File

@@ -6,8 +6,8 @@ import (
var MicroSeconds = newNumber().SetInt64(1000000) var MicroSeconds = newNumber().SetInt64(1000000)
func ArTimeClass(N time.Time) ArMap { func ArTimeClass(N time.Time) ArObject {
return ArMap{ return Map(anymap{
"__value__": newNumber().Quo(newNumber().SetInt64(N.UnixMicro()), MicroSeconds), "__value__": newNumber().Quo(newNumber().SetInt64(N.UnixMicro()), MicroSeconds),
"year": builtinFunc{ "year": builtinFunc{
"year", "year",
@@ -96,10 +96,10 @@ func ArTimeClass(N time.Time) ArMap {
return N.Format(a[0].(string)), ArErr{} return N.Format(a[0].(string)), ArErr{}
}, },
}, },
} })
} }
var ArTime = map[any]any{ var ArTime = Map(anymap{
"snooze": builtinFunc{"snooze", func(a ...any) (any, ArErr) { "snooze": builtinFunc{"snooze", func(a ...any) (any, ArErr) {
if len(a) > 0 { if len(a) > 0 {
float, _ := a[0].(number).Float64() float, _ := a[0].(number).Float64()
@@ -212,4 +212,4 @@ var ArTime = map[any]any{
} }
}, },
}, },
} })

View File

@@ -72,17 +72,17 @@ func anyToArgon(x any, quote bool, simplify bool, depth int, indent int, colored
if colored { if colored {
output = append(output, "\x1b[0m") output = append(output, "\x1b[0m")
} }
case ArMap: case ArObject:
if _, ok := x["__value__"]; ok { if x.TYPE == "array" {
return anyToArgon(x["__value__"], quote, simplify, depth, indent, colored, plain) return anyToArgon(x.obj["__value__"], quote, simplify, depth, indent, colored, plain)
} }
if len(x) == 0 { if len(x.obj) == 0 {
return "{}" return "{}"
} }
keys := make([]any, len(x)) keys := make([]any, len(x.obj))
i := 0 i := 0
for k := range x { for k := range x.obj {
keys[i] = k keys[i] = k
i++ i++
} }
@@ -103,13 +103,11 @@ func anyToArgon(x any, quote bool, simplify bool, depth int, indent int, colored
} }
keyval = strings.Join(outputkeyval, "") 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)) + "}" return "{" + maybenewline + (strings.Repeat(" ", (indent+1)*plain)) + strings.Join(output, ","+maybenewline+(strings.Repeat(" ", (indent+1)*plain))) + maybenewline + (strings.Repeat(" ", indent*plain)) + "}"
case ArArray: case []any:
if len(x) == 0 { singleline := len(x) <= 3
return "[]"
}
output := []string{} output := []string{}
if simplify && len(x) >= 100 { if simplify && len(x) >= 100 {
for i := 0; i < 10; i++ { for i := 0; i < 10; i++ {
@@ -128,9 +126,17 @@ func anyToArgon(x any, quote bool, simplify bool, depth int, indent int, colored
} else { } else {
for i := 0; i < len(x); i++ { for i := 0; i < len(x); i++ {
item := 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)) + "]" return "[" + maybenewline + (strings.Repeat(" ", (indent+1)*plain)) + strings.Join(output, ","+maybenewline+(strings.Repeat(" ", (indent+1)*plain))) + maybenewline + (strings.Repeat(" ", indent*plain)) + "]"
case builtinFunc: case builtinFunc:
if colored { if colored {

View File

@@ -1,7 +1,7 @@
package main package main
func typeof(val any) string { func typeof(val any) string {
switch val.(type) { switch x := val.(type) {
case number: case number:
return "number" return "number"
case string: case string:
@@ -14,10 +14,11 @@ func typeof(val any) string {
return "function" return "function"
case builtinFunc: case builtinFunc:
return "function" return "function"
case ArMap: case ArObject:
if x.TYPE == "array" {
return "array"
}
return "map" return "map"
case ArArray:
return "array"
case accessVariable: case accessVariable:
return "variable" return "variable"
} }

View File

@@ -78,7 +78,7 @@ func parseVariable(code UNPARSEcode) (accessVariable, bool, ArErr, int) {
func readVariable(v accessVariable, stack stack) (any, ArErr) { func readVariable(v accessVariable, stack stack) (any, ArErr) {
for i := len(stack) - 1; i >= 0; i-- { for i := len(stack) - 1; i >= 0; i-- {
varMutex.RLock() varMutex.RLock()
val, ok := stack[i][v.name] val, ok := stack[i].obj[v.name]
varMutex.RUnlock() varMutex.RUnlock()
if ok { if ok {
return val, ArErr{} return val, ArErr{}
@@ -208,30 +208,30 @@ func setVariableValue(v setVariable, stack stack, stacklevel int) (any, ArErr) {
if v.TYPE == "let" { if v.TYPE == "let" {
varMutex.RLock() varMutex.RLock()
_, ok := stack[len(stack)-1][v.toset.(accessVariable).name] _, ok := stack[len(stack)-1].obj[v.toset.(accessVariable).name]
varMutex.RUnlock() varMutex.RUnlock()
if ok { if ok {
return nil, ArErr{"Runtime Error", "variable \"" + v.toset.(accessVariable).name + "\" already exists", v.line, v.path, v.code, true} return nil, ArErr{"Runtime Error", "variable \"" + v.toset.(accessVariable).name + "\" already exists", v.line, v.path, v.code, true}
} }
varMutex.Lock() varMutex.Lock()
stack[len(stack)-1][v.toset.(accessVariable).name] = resp stack[len(stack)-1].obj[v.toset.(accessVariable).name] = resp
varMutex.Unlock() varMutex.Unlock()
} else { } else {
switch x := v.toset.(type) { switch x := v.toset.(type) {
case accessVariable: case accessVariable:
for i := len(stack) - 1; i >= 0; i-- { for i := len(stack) - 1; i >= 0; i-- {
varMutex.RLock() varMutex.RLock()
_, ok := stack[i][x.name] _, ok := stack[i].obj[x.name]
varMutex.RUnlock() varMutex.RUnlock()
if ok { if ok {
varMutex.Lock() varMutex.Lock()
stack[i][x.name] = resp stack[i].obj[x.name] = resp
varMutex.Unlock() varMutex.Unlock()
return ThrowOnNonLoop(resp, ArErr{}) return ThrowOnNonLoop(resp, ArErr{})
} }
} }
varMutex.Lock() varMutex.Lock()
stack[len(stack)-1][x.name] = resp stack[len(stack)-1].obj[x.name] = resp
varMutex.Unlock() varMutex.Unlock()
case ArMapGet: case ArMapGet:
respp, err := runVal(x.VAL, stack, stacklevel+1) 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 return nil, err
} }
switch y := respp.(type) { switch y := respp.(type) {
case ArMap: case ArObject:
if isUnhashable(key) { 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} return nil, ArErr{"Runtime Error", "can't use unhashable type as map key: " + typeof(key), v.line, v.path, v.code, true}
} }
varMutex.Lock() varMutex.Lock()
y[key] = resp y.obj[key] = resp
varMutex.Unlock() varMutex.Unlock()
default: default:
return nil, ArErr{"Runtime Error", "can't set for non map", v.line, v.path, v.code, true} 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) { switch x := d.value.(type) {
case accessVariable: case accessVariable:
for i := len(stack) - 1; i >= 0; i-- { for i := len(stack) - 1; i >= 0; i-- {
if _, ok := stack[i][x.name]; ok { if _, ok := stack[i].obj[x.name]; ok {
delete(stack[i], x.name) delete(stack[i].obj, x.name)
return nil, ArErr{} return nil, ArErr{}
} }
} }
@@ -304,8 +304,14 @@ func runDelete(d ArDelete, stack stack, stacklevel int) (any, ArErr) {
return nil, err return nil, err
} }
switch y := respp.(type) { switch y := respp.(type) {
case ArMap: case ArObject:
delete(y, key) 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: default:
return nil, ArErr{"Runtime Error", "can't delete for non map", d.line, d.path, d.code, true} return nil, ArErr{"Runtime Error", "can't delete for non map", d.line, d.path, d.code, true}
} }