diff --git a/src/boolean.go b/src/boolean.go index 64acccd..2b77152 100644 --- a/src/boolean.go +++ b/src/boolean.go @@ -18,8 +18,6 @@ func anyToBool(x any) bool { return true case Callable: return true - case ArClass: - return true default: return true } diff --git a/src/built-ins.go b/src/built-ins.go index 87f67c8..c7da8d0 100644 --- a/src/built-ins.go +++ b/src/built-ins.go @@ -165,4 +165,6 @@ func init() { vars["file"] = ArFile vars["random"] = ArRandom vars["json"] = ArJSON + vars["sin"] = ArSin + vars["arcsin"] = ArArcsin } diff --git a/src/getIndex.go b/src/getIndex.go index 6fdb5c9..4d19fc3 100644 --- a/src/getIndex.go +++ b/src/getIndex.go @@ -8,11 +8,6 @@ import ( type ArMap = map[any]any type ArArray = []any -type ArClass struct { - value any - MAP ArMap -} - var mapGetCompile = makeRegex(`(.|\n)+\.([a-zA-Z_]|(\p{L}\p{M}*))([a-zA-Z0-9_]|(\p{L}\p{M}*))*( *)`) var indexGetCompile = makeRegex(`(.|\n)+\[(.|\n)+\]( *)`) @@ -219,32 +214,6 @@ func mapGet(r ArMapGet, stack stack, stacklevel int) (any, ArErr) { } fmt.Println(startindex, endindex, step) return m[startindex:endindex], ArErr{} - case ArClass: - if r.numberofindex > 1 { - return nil, ArErr{ - "IndexError", - "index not found", - r.line, - r.path, - r.code, - true, - } - } - key, err := runVal(r.start, stack, stacklevel+1) - if err.EXISTS { - return nil, err - } - if _, ok := m.MAP[key]; !ok { - return nil, ArErr{ - "KeyError", - "key '" + fmt.Sprint(key) + "' not found", - r.line, - r.path, - r.code, - true, - } - } - return m.MAP[key], ArErr{} case string: startindex := 0 endindex := 1 @@ -404,8 +373,10 @@ func mapGet(r ArMapGet, stack stack, stacklevel int) (any, ArErr) { } func classVal(r any) any { - if _, ok := r.(ArClass); ok { - return r.(ArClass).value + if _, ok := r.(ArMap); ok { + if _, ok := r.(ArMap)["__value__"]; ok { + return r.(ArMap)["__value__"] + } } return r } diff --git a/src/import.go b/src/import.go index 37501e2..09a163e 100644 --- a/src/import.go +++ b/src/import.go @@ -44,7 +44,7 @@ func readFile(path string) []UNPARSEcode { return output } -func importMod(realpath string, origin string, main bool) (scope, ArErr) { +func importMod(realpath string, origin string) (scope, ArErr) { extention := filepath.Ext(realpath) path := realpath if extention == "" { diff --git a/src/jsonread.go b/src/jsonread.go index a4734b3..2a28aea 100644 --- a/src/jsonread.go +++ b/src/jsonread.go @@ -41,6 +41,7 @@ func parse(str string) any { func stringify(obj any) (string, error) { output := []string{} + obj = classVal(obj) switch x := obj.(type) { case ArMap: for key, value := range x { @@ -65,14 +66,13 @@ func stringify(obj any) (string, error) { case string: return strconv.Quote(x), nil case number: - num, _ := x.Float64() - return strconv.FormatFloat(num, 'f', -1, 64), nil + return anyToArgon(x, true, false, 1, 0, false, 0), nil case bool: return strconv.FormatBool(x), nil case nil: return "null", nil } - err := errors.New("Cannot stringify " + typeof(obj)) + err := errors.New("Cannot stringify '" + typeof(obj) + "'") return "", err } diff --git a/src/main.go b/src/main.go index 71e84ed..3778238 100644 --- a/src/main.go +++ b/src/main.go @@ -19,7 +19,7 @@ func main() { shell() os.Exit(0) } - _, err := importMod(Args[0], ex, true) + _, err := importMod(Args[0], ex) if err.EXISTS { panicErr(err) os.Exit(1) diff --git a/src/parseImport.go b/src/parseImport.go new file mode 100644 index 0000000..ec05c07 --- /dev/null +++ b/src/parseImport.go @@ -0,0 +1,76 @@ +package main + +import ( + "os" + "strings" +) + +var genericImportCompiled = makeRegex(`import( )+(.|\n)+( )+as( )+([a-zA-Z_]|(\p{L}\p{M}*))([a-zA-Z0-9_]|(\p{L}\p{M}*))*( *)`) + +type ArImport struct { + filePath any + values any + code string + line int + path string +} + +func isGenericImport(code UNPARSEcode) bool { + return genericImportCompiled.MatchString(code.code) +} + +func parseGenericImport(code UNPARSEcode, index int, codeline []UNPARSEcode) (ArImport, bool, ArErr, int) { + trim := strings.Trim(code.code, " ") + pathAndAs := trim[6:] + split := strings.SplitN(pathAndAs, " as ", 2) + toImportstr := strings.TrimSpace(split[0]) + asStr := strings.TrimSpace(split[1]) + toImport, worked, err, i := translateVal(UNPARSEcode{ + code: toImportstr, + realcode: code.realcode, + line: code.line, + path: code.path, + }, index, codeline, 0) + if !worked { + return ArImport{}, false, err, i + } + return ArImport{ + toImport, + asStr, + code.realcode, + code.line, + code.path, + }, true, ArErr{}, i +} + +func runImport(importOBJ ArImport, stack stack, stacklevel int) (any, ArErr) { + val, err := runVal(importOBJ.filePath, stack, stacklevel+1) + if err.EXISTS { + return nil, err + } + if typeof(val) != "string" { + return nil, ArErr{"Type Error", "import requires a string, got type '" + typeof(val) + "'", importOBJ.line, importOBJ.path, importOBJ.code, true} + } + path := val.(string) + ex, e := os.Getwd() + 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) + if err.EXISTS { + return nil, err + } + switch x := importOBJ.values.(type) { + case []string: + for _, v := range x { + val, ok := stackMap[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 + } + case string: + stack[len(stack)-1][x] = stackMap + } + return nil, ArErr{} +} diff --git a/src/run.go b/src/run.go index fdc4777..ec560fc 100644 --- a/src/run.go +++ b/src/run.go @@ -7,6 +7,7 @@ import ( // returns (number|string|nil), error func runVal(line any, stack stack, stacklevel int) (any, ArErr) { + fmt.Println(stack) if stacklevel > 10000 { return nil, ArErr{ TYPE: "RuntimeError", @@ -30,8 +31,6 @@ func runVal(line any, stack stack, stacklevel int) (any, ArErr) { return readVariable(x, stack) case ArMapGet: return mapGet(x, stack, stacklevel+1) - case ArClass: - return x.MAP, ArErr{} case setVariable: return setVariableValue(x, stack, stacklevel+1) case negative: @@ -69,6 +68,10 @@ func runVal(line any, stack stack, stacklevel int) (any, ArErr) { return runWhileLoop(x, stack, stacklevel+1) case CreateArray: return runArray(x, stack, stacklevel+1) + case squareroot: + return runSquareroot(x, stack, stacklevel+1) + case ArImport: + return runImport(x, stack, stacklevel+1) case bool: return x, ArErr{} case nil: diff --git a/src/squareroot.go b/src/squareroot.go new file mode 100644 index 0000000..d7bbe0e --- /dev/null +++ b/src/squareroot.go @@ -0,0 +1,74 @@ +package main + +import ( + "math/big" + "strings" +) + +var squarerootcompiled = makeRegex(`(.|\n)*√(.|\n)+`) + +type squareroot struct { + first any + second any + code string + line int + path string +} + +func issquareroot(code UNPARSEcode) bool { + return squarerootcompiled.MatchString(code.code) +} + +func parseSquareroot(code UNPARSEcode, index int, lines []UNPARSEcode) (squareroot, bool, ArErr, int) { + split := strings.SplitN(code.code, "√", 2) + first := strings.TrimSpace(split[0]) + second := strings.TrimSpace(split[1]) + var firstparsed any = newNumber().SetInt64(1) + outputlen := 0 + if first != "" { + val, worked, err, i := translateVal(UNPARSEcode{code: first, realcode: code.realcode, line: code.line, path: code.path}, index, lines, 0) + if !worked { + return squareroot{}, false, err, i + } + outputlen += i - 1 + firstparsed = val + } + secondparsed, worked, err, i := translateVal(UNPARSEcode{code: second, realcode: code.realcode, line: code.line, path: code.path}, index, lines, 0) + if !worked { + return squareroot{}, false, err, i + } + outputlen += i + return squareroot{ + firstparsed, + secondparsed, + code.realcode, + code.line, + code.path, + }, true, ArErr{}, outputlen +} + +func runSquareroot(squareroot squareroot, stack stack, stacklevel int) (number, ArErr) { + val1, err := runVal(squareroot.first, stack, stacklevel+1) + if err.EXISTS { + return nil, err + } + val2, err := runVal(squareroot.second, stack, stacklevel+1) + if err.EXISTS { + return nil, err + } + if typeof(val1) != "number" || typeof(val2) != "number" { + return nil, ArErr{"Type Error", "Cannot take the square root of a non-number", squareroot.line, squareroot.path, squareroot.code, true} + } + + var x big.Float + x.SetPrec(30) + x.SetRat(val2.(number)) + + var s big.Float + s.SetPrec(15) + s.Sqrt(&x) + + r, _ := s.Rat(nil) + r.Mul(r, val1.(number)) + return r, ArErr{} +} diff --git a/src/time.go b/src/time.go index 408e672..09048e0 100644 --- a/src/time.go +++ b/src/time.go @@ -6,98 +6,97 @@ import ( var MicroSeconds = newNumber().SetInt64(1000000) -func ArTimeClass(N time.Time) ArClass { - return ArClass{ - newNumber().Quo(newNumber().SetInt64(N.UnixMicro()), MicroSeconds), - ArMap{ - "year": builtinFunc{ - "year", - func(a ...any) (any, ArErr) { - return newNumber().SetInt64(int64(N.Year())), ArErr{} - }, +func ArTimeClass(N time.Time) ArMap { + return ArMap{ + "__value__": newNumber().Quo(newNumber().SetInt64(N.UnixMicro()), MicroSeconds), + "year": builtinFunc{ + "year", + func(a ...any) (any, ArErr) { + return newNumber().SetInt64(int64(N.Year())), ArErr{} }, - "month": builtinFunc{ - "month", - func(a ...any) (any, ArErr) { - return N.Month().String(), ArErr{} - }, + }, + "month": builtinFunc{ + "month", + func(a ...any) (any, ArErr) { + return N.Month().String(), ArErr{} }, - "day": builtinFunc{ - "day", - func(a ...any) (any, ArErr) { - return newNumber().SetInt64(int64(N.Day())), ArErr{} - }, + }, + "day": builtinFunc{ + "day", + func(a ...any) (any, ArErr) { + return newNumber().SetInt64(int64(N.Day())), ArErr{} }, - "hour": builtinFunc{ - "hour", - func(a ...any) (any, ArErr) { - return newNumber().SetInt64(int64(N.Hour())), ArErr{} - }, + }, + "hour": builtinFunc{ + "hour", + func(a ...any) (any, ArErr) { + return newNumber().SetInt64(int64(N.Hour())), ArErr{} }, - "minute": builtinFunc{ - "minute", - func(a ...any) (any, ArErr) { - return newNumber().SetInt64(int64(N.Minute())), ArErr{} - }, + }, + "minute": builtinFunc{ + "minute", + func(a ...any) (any, ArErr) { + return newNumber().SetInt64(int64(N.Minute())), ArErr{} }, - "second": builtinFunc{ - "second", - func(a ...any) (any, ArErr) { - return newNumber().SetInt64(int64(N.Second())), ArErr{} - }, + }, + "second": builtinFunc{ + "second", + func(a ...any) (any, ArErr) { + return newNumber().SetInt64(int64(N.Second())), ArErr{} }, - "nanosecond": builtinFunc{ - "nanosecond", - func(a ...any) (any, ArErr) { - return newNumber().SetInt64(int64(N.Nanosecond())), ArErr{} - }, + }, + "nanosecond": builtinFunc{ + "nanosecond", + func(a ...any) (any, ArErr) { + return newNumber().SetInt64(int64(N.Nanosecond())), ArErr{} }, - "weekday": builtinFunc{ - "weekday", - func(a ...any) (any, ArErr) { - return N.Weekday().String(), ArErr{} - }, + }, + "weekday": builtinFunc{ + "weekday", + func(a ...any) (any, ArErr) { + return N.Weekday().String(), ArErr{} }, - "yearDay": builtinFunc{ - "yearDay", - func(a ...any) (any, ArErr) { - return newNumber().SetInt64(int64(N.YearDay())), ArErr{} - }, + }, + "yearDay": builtinFunc{ + "yearDay", + func(a ...any) (any, ArErr) { + return newNumber().SetInt64(int64(N.YearDay())), ArErr{} }, - "unix": builtinFunc{ - "unix", - func(a ...any) (any, ArErr) { - return newNumber().SetInt64(N.Unix()), ArErr{} - }, + }, + "unix": builtinFunc{ + "unix", + func(a ...any) (any, ArErr) { + return newNumber().SetInt64(N.Unix()), ArErr{} }, - "unixNano": builtinFunc{ - "unixNano", - func(a ...any) (any, ArErr) { - return newNumber().SetInt64(N.UnixNano()), ArErr{} - }, + }, + "unixNano": builtinFunc{ + "unixNano", + func(a ...any) (any, ArErr) { + return newNumber().SetInt64(N.UnixNano()), ArErr{} }, - "unixMilli": builtinFunc{ - "unixMilli", - func(a ...any) (any, ArErr) { - return newNumber().SetInt64(N.UnixMilli()), ArErr{} - }, + }, + "unixMilli": builtinFunc{ + "unixMilli", + func(a ...any) (any, ArErr) { + return newNumber().SetInt64(N.UnixMilli()), ArErr{} }, - "unixMicro": builtinFunc{ - "unixMicro", - func(a ...any) (any, ArErr) { - return newNumber().SetInt64(N.UnixMicro()), ArErr{} - }, + }, + "unixMicro": builtinFunc{ + "unixMicro", + func(a ...any) (any, ArErr) { + return newNumber().SetInt64(N.UnixMicro()), ArErr{} }, - "format": builtinFunc{ - "date", - func(a ...any) (any, ArErr) { - if len(a) == 0 { - return N.Format(time.UnixDate), ArErr{} - } - return N.Format(a[0].(string)), ArErr{} - }, + }, + "format": builtinFunc{ + "date", + func(a ...any) (any, ArErr) { + if len(a) == 0 { + return N.Format(time.UnixDate), ArErr{} + } + return N.Format(a[0].(string)), ArErr{} }, - }} + }, + } } var ArTime = map[any]any{ diff --git a/src/to-argon.go b/src/to-argon.go index 076a6a0..4b53e63 100644 --- a/src/to-argon.go +++ b/src/to-argon.go @@ -73,6 +73,9 @@ func anyToArgon(x any, quote bool, simplify bool, depth int, indent int, colored output = append(output, "\x1b[0m") } case ArMap: + if _, ok := x["__value__"]; ok { + return anyToArgon(x["__value__"], quote, simplify, depth, indent, colored, plain) + } if len(x) == 0 { return "{}" } @@ -85,7 +88,22 @@ func anyToArgon(x any, quote bool, simplify bool, depth int, indent int, colored } output := []string{} for _, key := range keys { - output = append(output, anyToArgon(key, true, true, depth, (indent+1)*plain, colored, plain)+": "+anyToArgon(x[key], true, true, depth-1, indent+1, colored, plain)) + keyval := "" + + if typeof(key) != "string" || !SpacelessVariableCompiled.MatchString(key.(string)) { + keyval = anyToArgon(key, true, true, depth-1, indent+1, colored, plain) + } else { + outputkeyval := []string{} + if colored { + outputkeyval = append(outputkeyval, "\x1b[36;5;240m") + } + outputkeyval = append(outputkeyval, key.(string)) + if colored { + outputkeyval = append(outputkeyval, "\x1b[0m") + } + keyval = strings.Join(outputkeyval, "") + } + output = append(output, keyval+": "+anyToArgon(x[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: @@ -130,8 +148,6 @@ func anyToArgon(x any, quote bool, simplify bool, depth int, indent int, colored if colored { output = append(output, "\x1b[0m") } - case ArClass: - return anyToArgon(x.value, quote, simplify, depth, indent, colored, plain) default: return fmt.Sprint(x) } diff --git a/src/translate.go b/src/translate.go index d2ac357..b8d4671 100644 --- a/src/translate.go +++ b/src/translate.go @@ -1,6 +1,7 @@ package main import ( + "fmt" "strings" ) @@ -13,7 +14,7 @@ type UNPARSEcode struct { // returns (number | string | nil), success, error, step func translateVal(code UNPARSEcode, index int, codelines []UNPARSEcode, isLine int) (any, bool, ArErr, int) { - + fmt.Println(code) if isLine == 2 { if isDeleteVariable(code) { return parseDelete(code, index, codelines) @@ -32,6 +33,8 @@ func translateVal(code UNPARSEcode, index int, codelines []UNPARSEcode, isLine i return parseWhileLoop(code, index, codelines) } else if isForeverLoop(code) { return parseForeverLoop(code, index, codelines) + } else if isGenericImport(code) { + return parseGenericImport(code, index, codelines) } } @@ -95,6 +98,8 @@ func translateVal(code UNPARSEcode, index int, codelines []UNPARSEcode, isLine i return indexGetParse(code, index, codelines) } else if isString(code) { return parseString(code) + } else if issquareroot(code) { + return parseSquareroot(code, index, codelines) } return nil, false, ArErr{"Syntax Error", "invalid syntax", code.line, code.path, code.realcode, true}, 1 } diff --git a/src/trig.go b/src/trig.go new file mode 100644 index 0000000..9a91d4a --- /dev/null +++ b/src/trig.go @@ -0,0 +1,59 @@ +package main + +import ( + "fmt" + "math" +) + +var PIFloatInaccuracy number = newNumber() + +func init() { + PIFloatInaccuracy.SetFloat64(math.Asin(1) * 2) +} + +var ArSin = builtinFunc{"sin", func(args ...any) (any, ArErr) { + if len(args) != 1 { + return nil, ArErr{TYPE: "Runtime Error", + message: fmt.Sprintf("sin expected 1 argument, got %d", len(args)), + EXISTS: true, + } + } + if typeof(args[0]) != "number" { + return nil, ArErr{TYPE: "Runtime Error", + message: fmt.Sprintf("sin expected number, got %s", typeof(args[0])), + EXISTS: true, + } + } + num := newNumber().Set(args[0].(number)) + num.Quo(num, PI) + num.Mul(num, PIFloatInaccuracy) + n, _ := num.Float64() + outputnum := newNumber().SetFloat64(math.Sin(n)) + return outputnum, ArErr{} +}} +var ArArcsin = builtinFunc{"arcsin", func(args ...any) (any, ArErr) { + if len(args) != 1 { + return nil, ArErr{TYPE: "Runtime Error", + message: fmt.Sprintf("arcsin expected 1 argument, got %d", len(args)), + EXISTS: true, + } + } + if typeof(args[0]) != "number" { + return nil, ArErr{TYPE: "Runtime Error", + message: fmt.Sprintf("arcsin expected number, got %s", typeof(args[0])), + EXISTS: true, + } + } + num := args[0].(number) + n, _ := num.Float64() + if n < -1 || n > 1 { + return nil, ArErr{TYPE: "Runtime Error", + message: fmt.Sprintf("arcsin expected number between -1 and 1, got %s", anyToArgon(n, true, true, 3, 0, false, 0)), + EXISTS: true, + } + } + outputnum := newNumber().SetFloat64(math.Asin(n)) + outputnum.Quo(outputnum, PIFloatInaccuracy) + outputnum.Mul(outputnum, PI) + return outputnum, ArErr{} +}} diff --git a/src/variable.go b/src/variable.go index 5271fbd..a67472c 100644 --- a/src/variable.go +++ b/src/variable.go @@ -1,10 +1,12 @@ package main import ( + "fmt" "strings" "sync" ) +var SpacelessVariableCompiled = makeRegex(`([a-zA-Z_]|(\p{L}\p{M}*))([a-zA-Z0-9_]|(\p{L}\p{M}*))*`) var variableCompile = makeRegex(`( *)([a-zA-Z_]|(\p{L}\p{M}*))([a-zA-Z0-9_]|(\p{L}\p{M}*))*( *)`) var validname = makeRegex(`(.|\n)*(\(( *)((([a-zA-Z_]|(\p{L}\p{M}*))([a-zA-Z0-9_]|(\p{L}\p{M}*))*)(( *)\,( *)([a-zA-Z_]|(\p{L}\p{M}*))([a-zA-Z0-9_]|(\p{L}\p{M}*))*)*)?( *)\))`) var setVariableCompile = makeRegex(`( *)(let( +))(.|\n)+( *)=(.|\n)+`) @@ -162,6 +164,7 @@ func parseSetVariable(code UNPARSEcode, index int, lines []UNPARSEcode, isLine i } func parseAutoAsignVariable(code UNPARSEcode, index int, lines []UNPARSEcode, isLine int) (setVariable, bool, ArErr, int) { + fmt.Println("autoasign", code.code) trim := strings.TrimSpace(code.code) equalsplit := strings.SplitN(trim, "=", 2) name := strings.TrimSpace(equalsplit[0]) @@ -190,6 +193,7 @@ func parseAutoAsignVariable(code UNPARSEcode, index int, lines []UNPARSEcode, is if !success { return setVariable{}, false, err, i } + fmt.Println("autoasign", code.code, "success") return setVariable{TYPE: "auto", toset: toset, value: value, function: function, params: params, line: code.line, code: code.code, path: code.path}, true, ArErr{}, i + namei - 1 } diff --git a/test.ar b/test.ar index 38c7218..315cf2d 100644 --- a/test.ar +++ b/test.ar @@ -1,8 +1,4 @@ -a = array() -i = 0 - -forever do - a = append(a, i) - i = i + 1 - if (i % 1000000 == 0) do - term.log(i) \ No newline at end of file +test = 10 +poo = do + term.log("ran") + return "lol" \ No newline at end of file