add functions and variables name

This commit is contained in:
2023-02-25 23:34:15 +00:00
parent 636101f1fa
commit 6ef6e051e6
23 changed files with 414 additions and 97 deletions

View File

@@ -1,3 +1,3 @@
@echo off
go build -o bin/Argon-v3.exe ./src
go build -o bin/argon.exe ./src

1
build.sh Normal file
View File

@@ -0,0 +1 @@
go build -o bin/argon ./src

View File

@@ -10,6 +10,7 @@ ARGON 3 is a math-driven programming language designed to make code easy to read
## 📚 Features
- Easy to read and write: Argon 3 is designed with clarity of code in mind, making it easier for you and others to read and write code.
- All numbers are stored as rational numbers, preventing precision errors.
- Math-driven: Designed for mathematical computations, Argon 3 uses techniques and rules set in maths. It's designed to be easy for mathematicians to write and understand algorithms in.
- Interpreted: Argon 3 is an interpreted language, so you don't need to compile your code before running it.
- Cross-platform: Argon 3 can be run on any platform that has an interpreter for it.

View File

@@ -64,7 +64,7 @@ output:
f(10) = 121
```
if the function does not return, then the value returned is `unknown`
if the function does not return, then the value returned is `null`
---

34
src/built-in-functions.go Normal file
View File

@@ -0,0 +1,34 @@
package main
import "fmt"
type builtinFunc struct {
name string
FUNC func(...any) (any, ArErr)
}
func ArgonLog(args ...any) (any, ArErr) {
output := []any{}
for i := 0; i < len(args); i++ {
output = append(output, anyToArgon(args[i], false))
}
fmt.Println(output...)
return nil, ArErr{}
}
func ArgonAdd(args ...any) (any, ArErr) {
return reduce(func(x any, y any) any {
return newNumber().Add(x.(number), y.(number))
}, args), ArErr{}
}
func ArgonDiv(args ...any) (any, ArErr) {
return reduce(func(x any, y any) any {
return newNumber().Quo(y.(number), x.(number))
}, args), ArErr{}
}
func ArgonMult(args ...any) (any, ArErr) {
return reduce(func(x any, y any) any {
return newNumber().Mul(y.(number), x.(number))
}, args), ArErr{}
}

27
src/built-ins.go Normal file
View File

@@ -0,0 +1,27 @@
package main
var vars = map[string]variableValue{}
func init() {
vars["log"] = variableValue{
EXISTS: true,
VAL: builtinFunc{"log", ArgonLog},
}
vars["add"] = variableValue{
EXISTS: true,
VAL: builtinFunc{"add", ArgonAdd},
}
vars["div"] = variableValue{
EXISTS: true,
VAL: builtinFunc{"div", ArgonDiv},
}
vars["mult"] = variableValue{
EXISTS: true,
VAL: builtinFunc{"mult", ArgonMult},
}
pi, _ := newNumber().SetString("3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679821480865132823066470938446095505822317253594081284811174502841027019385211055596446229489549303819644288109756659334461284756482337867831652712019091456485669234603486104543266482133936072602491412737245870066063155881748815209209628292540917153643678925903600113305305488204665213841469519415116094330572703657595919530921861173819326117931051185480744623799627495673518857527248912279381830119491298336733624406566430860213949463952247371907021798609437027705392171762931767523846748184676694051320005681271452635608277857713427577896091736371787214684409012249534301465495853710507922796892589235420199561121290219608640344181598136297747713099605187072113499999983729780499510597317328160963185950244594553469083026425223082533446850352619311881710100031378387528865875332083814206171776691473035982534904287554687311595628638823537875937519577818577805321712268066130019278766111959092164201989")
vars["PI"] = variableValue{
EXISTS: true,
VAL: pi,
}
}

76
src/call.go Normal file
View File

@@ -0,0 +1,76 @@
package main
import (
"strings"
)
var callCompile = makeRegex("( *).+\\(.*\\)( *)")
type call struct {
callable any
args []any
code string
line int
}
func isCall(code UNPARSEcode) bool {
return callCompile.MatchString(code.code)
}
func parseCall(code UNPARSEcode, index int, codelines []UNPARSEcode) (any, bool, ArErr, int) {
trim := strings.TrimSpace(code.code)
trim = trim[:len(trim)-1]
splitby := strings.Split(trim, "(")
var works bool
var callable any
var arguments []any
for i := 1; i < len(splitby); i++ {
name := strings.Join(splitby[0:i], "(")
argstr := strings.Join(splitby[i:], "(")
args, success, argserr := getValuesFromCommas(argstr, index, codelines)
arguments = args
if !success {
if i == len(splitby)-1 {
return nil, false, argserr, 1
}
continue
}
resp, worked, _, _ := translateVal(UNPARSEcode{code: name, realcode: code.realcode, line: index + 1, path: code.path}, index, codelines, false)
if !worked {
if i == len(splitby)-1 {
return nil, false, ArErr{"Syntax Error", "invalid callable", code.line, code.path, code.realcode, true}, 1
}
continue
}
works = true
callable = resp
break
}
if !works {
return nil, false, ArErr{"Syntax Error", "invalid call", code.line, code.path, code.realcode, true}, 1
}
return call{callable: callable, args: arguments, line: code.line, code: code.code}, true, ArErr{}, 1
}
func runCall(c call, stack []map[string]variableValue) (any, ArErr) {
callable, err := runVal(c.callable, stack)
if err.EXISTS {
return nil, err
}
args := []any{}
for _, arg := range c.args {
resp, err := runVal(arg, stack)
if err.EXISTS {
return nil, err
}
args = append(args, resp)
}
switch x := callable.(type) {
case builtinFunc:
return x.FUNC(args...)
case Callable:
return nil, ArErr{"Runtime Error", "cannot call a class", c.line, "", c.code, true}
}
return nil, ArErr{"Runtime Error", typeof(callable) + "' is not callable", c.line, "", c.code, true}
}

9
src/callable.go Normal file
View File

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

27
src/commaseperate.go Normal file
View File

@@ -0,0 +1,27 @@
package main
import (
"strings"
)
func getValuesFromCommas(str string, index int, codelines []UNPARSEcode) ([]any, bool, ArErr) {
// make a function which takes a string of code and returns a translated values
str = strings.Trim(str, " ")
commasplit := strings.Split(str, ",")
temp := []string{}
arguments := []any{}
if str != "" {
for i, arg := range commasplit {
temp = append(temp, arg)
test := strings.TrimSpace(strings.Join(temp, ","))
resp, worked, _, _ := translateVal(UNPARSEcode{code: test, realcode: codelines[index].realcode, line: index + 1, path: codelines[index].path}, index, codelines, false)
if worked {
arguments = append(arguments, resp)
temp = []string{}
} else if i == len(commasplit)-1 {
return nil, false, ArErr{"Syntax Error", "invalid argument", codelines[index].line, codelines[index].path, codelines[index].realcode, true}
}
}
}
return arguments, true, ArErr{}
}

View File

@@ -1,7 +1,29 @@
package main
var commentCompile = makeRegex("( *)//.*")
import (
"strings"
)
var commentCompile = makeRegex(".*//.*")
func isComment(code UNPARSEcode) bool {
return commentCompile.MatchString(code.code)
}
func isBlank(code UNPARSEcode) bool {
return strings.TrimSpace(code.code) == ""
}
func parseComment(code UNPARSEcode, index int, codelines []UNPARSEcode) (any, bool, ArErr) {
split := strings.Split(code.code, "//")
temp := []string{}
for i := 0; i < len(split)-1; i++ {
temp = append(temp, split[i])
joined := strings.Join(temp, "//")
resp, worked, _, _ := translateVal(UNPARSEcode{code: joined, realcode: code.realcode, line: code.line, path: code.path}, index, codelines, true)
if worked {
return resp, true, ArErr{}
}
}
return nil, false, ArErr{"Syntax Error", "invalid comment", code.line, code.path, code.realcode, true}
}

23
src/error.go Normal file
View File

@@ -0,0 +1,23 @@
package main
import (
"fmt"
"os"
)
type ArErr struct {
TYPE string
message string
line int
path string
code string
EXISTS bool
}
func panicErr(err ArErr) {
fmt.Println(" File:", err.path+":"+fmt.Sprint(err.line))
fmt.Println(" " + err.code)
fmt.Println()
fmt.Println(err.TYPE+":", err.message)
os.Exit(1)
}

View File

@@ -32,7 +32,8 @@ func readFile(path string) []UNPARSEcode {
output := []UNPARSEcode{}
line := 1
for scanner.Scan() {
output = append(output, UNPARSEcode{scanner.Text(), line})
text := scanner.Text()
output = append(output, UNPARSEcode{text, text, line, path})
line++
}
@@ -43,7 +44,7 @@ func readFile(path string) []UNPARSEcode {
return output
}
func importMod(realpath string, origin string, main bool) string {
func importMod(realpath string, origin string, main bool) ArErr {
extention := filepath.Ext(realpath)
path := realpath
if extention == "" {
@@ -51,11 +52,11 @@ func importMod(realpath string, origin string, main bool) string {
}
ex, err := os.Getwd()
if err != nil {
return err.Error()
return ArErr{"Import Error", err.Error(), 0, realpath, "", true}
}
executable, err := os.Executable()
if err != nil {
return err.Error()
return ArErr{"Import Error", err.Error(), 0, realpath, "", true}
}
executable = filepath.Dir(executable)
isABS := filepath.IsAbs(path)
@@ -89,14 +90,17 @@ func importMod(realpath string, origin string, main bool) string {
}
if !found {
return "File does not exist: " + realpath
return ArErr{"Import Error", "File does not exist: " + realpath, 0, realpath, "", true}
}
codelines := readFile(p)
translated, translationerr := translate(codelines)
if translationerr != "" {
if translationerr.EXISTS {
return translationerr
}
run(translated)
return ""
_, runimeErr := run(translated, []map[string]variableValue{vars})
if runimeErr.EXISTS {
return runimeErr
}
return ArErr{}
}

View File

@@ -8,7 +8,6 @@ import (
var Args = os.Args[1:]
func main() {
ex, e := os.Getwd()
if e != nil {
panic(e)
@@ -17,7 +16,7 @@ func main() {
panic("No file specified")
}
err := importMod(Args[0], ex, true)
if err != "" {
panic(err)
if err.EXISTS {
panicErr(err)
}
}

View File

@@ -6,7 +6,16 @@ import (
"strings"
)
var numberCompile = makeRegex("( *)((\\-)?(([0-9]*(\\.[0-9]+)?)(e((\\-|\\+)?([0-9]+(\\.[0-9]+)?)))?)|(0b[10]+(.[10]+)?(e((\\-|\\+)?([0-9]+(\\.[0-9]+)?)))?)|(0x[a-fA-F0-9]+(.[a-fA-F0-9]+)?)|(0o[0-7]+(.[0-7]+)?(e((\\-|\\+)?([0-9]+(\\.[0-9]+)?)))?))( *)")
type translateNumber struct {
number
code string
line int
}
var numberCompile = makeRegex("( *)(\\-)?((([0-9]+(\\.[0-9]+)?)|(\\.[0-9]+))(e((\\-|\\+)?([0-9]+(\\.[0-9]+)?)))?)( *)")
var binaryCompile = makeRegex("( *)(0b[10]+(.[10]+)?(e((\\-|\\+)?([0-9]+(\\.[0-9]+)?)))?)( *)")
var hexCompile = makeRegex("( *)(0x[a-fA-F0-9]+(.[a-fA-F0-9]+)?)( *)")
var octalCompile = makeRegex("( *)(0o[0-7]+(.[0-7]+)?(e((\\-|\\+)?([0-9]+(\\.[0-9]+)?)))?)( *)")
// a number type
type number = *big.Rat
@@ -22,7 +31,7 @@ func stringToNumber(str string) (*big.Rat, bool) {
}
func isNumber(code UNPARSEcode) bool {
return numberCompile.MatchString(code.code)
return numberCompile.MatchString(code.code) || binaryCompile.MatchString(code.code) || hexCompile.MatchString(code.code) || octalCompile.MatchString(code.code)
}
// converts a number type to a string
@@ -80,10 +89,10 @@ var subscript = map[byte]string{
}
// returns translateNumber, success, error
func parseNumber(code UNPARSEcode) (translateNumber, bool, string) {
output, _ := newNumber().SetString(code.code)
func parseNumber(code UNPARSEcode) (translateNumber, bool, ArErr, int) {
output, _ := newNumber().SetString(strings.TrimSpace(code.code))
return translateNumber{
number: output,
line: code.line,
}, true, ""
}, true, ArErr{}, 1
}

9
src/reduce.go Normal file
View File

@@ -0,0 +1,9 @@
package main
func reduce[T any](reducer func(x T, y T) T, arr []T) T {
result := arr[0]
for i := 1; i < len(arr); i++ {
result = reducer(arr[i], result)
}
return result
}

View File

@@ -1,24 +1,27 @@
package main
import "fmt"
func runLine(line any) (any, string) {
switch line.(type) {
// returns (number|string|nil), error
func runVal(line any, stack []map[string]variableValue) (any, ArErr) {
switch x := line.(type) {
case translateNumber:
return (numberToString(line.(translateNumber).number, 0)), ""
return (x.number), ArErr{}
case translateString:
return (line.(translateString).str), ""
return (x.str), ArErr{}
case call:
return runCall(x, stack)
case accessVariable:
return readVariable(x, stack)
}
return nil, "Error: invalid code on line " + fmt.Sprint(line.(translateNumber).line) + ": " + line.(translateNumber).code
panic("unreachable")
}
// returns error
func run(translated []any) (any, string) {
func run(translated []any, stack []map[string]variableValue) (any, ArErr) {
for _, val := range translated {
_, err := runLine(val)
if err != "" {
_, err := runVal(val, stack)
if err.EXISTS {
return nil, err
}
}
return nil, ""
return nil, ArErr{}
}

View File

@@ -1,11 +1,16 @@
package main
import (
"fmt"
"strconv"
"strings"
)
type translateString struct {
str string
code string
line int
}
var stringCompile = makeRegex("(( *)\"((\\\\([a-z\\\"'`]))|[^\\\"])*\"( *))|(( *)'((\\\\([a-z\\'\"`]))|[^\\'])*'( *))")
func isString(code UNPARSEcode) bool {
@@ -27,16 +32,16 @@ func unquoted(
}
// returns translateString, success, error
func parseString(code UNPARSEcode) (translateString, bool, string) {
func parseString(code UNPARSEcode) (translateString, bool, ArErr, int) {
trim := strings.Trim(code.code, " ")
unquoted, err := unquoted(trim)
if err != nil {
return translateString{}, false, "Syntax Error: invalid string on line " + fmt.Sprint(code.line) + ": " + code.code
return translateString{}, false, ArErr{"Syntax Error", "invalid string", code.line, code.path, code.realcode, true}, 1
}
return translateString{
str: unquoted,
line: code.line,
}, true, ""
}, true, ArErr{}, 1
}

30
src/to-argon.go Normal file
View File

@@ -0,0 +1,30 @@
package main
import (
"fmt"
"math"
"strconv"
)
func anyToArgon(x any, quote bool) string {
switch x := x.(type) {
case string:
if !quote {
return x
}
return strconv.Quote(x)
case number:
num, _ := x.Float64()
if math.IsNaN(num) {
return "NaN"
} else if math.IsInf(num, 1) {
return "infinity"
} else if math.IsInf(num, -1) {
return "-infinity"
} else {
return strconv.FormatFloat(num, 'f', -1, 64)
}
default:
return fmt.Sprint(x)
}
}

View File

@@ -1,37 +1,43 @@
package main
import (
"fmt"
"log"
)
type UNPARSEcode struct {
code string
realcode string
line int
path string
}
// returns (translateNumber | translateString), success, error
func translateVal(code UNPARSEcode, index int, codelines []UNPARSEcode, isLine bool) (any, bool, string) {
// returns (translateNumber | translateString| nil), success, error
func translateVal(code UNPARSEcode, index int, codelines []UNPARSEcode, isLine bool) (any, bool, ArErr, int) {
if isLine {
if isComment(code) {
return nil, true, ""
if isBlank(code) {
return nil, true, ArErr{}, 1
} else if isComment(code) {
resp, worked, err := parseComment(code, index, codelines)
if worked {
return resp, worked, err, 1
}
}
}
if isNumber(code) {
if isCall(code) {
return parseCall(code, index, codelines)
} else if isVariable(code) {
return parseVariable(code)
} else if isNumber(code) {
return parseNumber(code)
} else if isString(code) {
return parseString(code)
}
if isLine {
return nil, false, "Syntax Error: invalid code on line " + fmt.Sprint(code.line) + ": " + code.code
}
return nil, false, ""
return nil, false, ArErr{"Syntax Error", "invalid syntax", code.line, code.path, code.realcode, true}, 1
}
// returns [](translateNumber | translateString), error
func translate(codelines []UNPARSEcode) ([]any, string) {
func translate(codelines []UNPARSEcode) ([]any, ArErr) {
translated := []any{}
for i, code := range codelines {
val, _, err := translateVal(code, i, codelines, true)
val, _, err, _ := translateVal(code, i, codelines, true)
if err != "" {
log.Fatal(err)
if err.EXISTS {
return nil, err
}
if val == nil {
@@ -39,5 +45,5 @@ func translate(codelines []UNPARSEcode) ([]any, string) {
}
translated = append(translated, val)
}
return translated, ""
return translated, ArErr{}
}

19
src/typeof.go Normal file
View File

@@ -0,0 +1,19 @@
package main
func typeof(val any) string {
switch val.(type) {
case number:
return "number"
case string:
return "string"
case nil:
return "null"
case bool:
return "boolean"
case Callable:
return "function"
case builtinFunc:
return "function"
}
return "unknown"
}

View File

@@ -1,18 +0,0 @@
package main
type UNPARSEcode struct {
code string
line int
}
type translateNumber struct {
number
code string
line int
}
type translateString struct {
str string
code string
line int
}

56
src/variable.go Normal file
View File

@@ -0,0 +1,56 @@
package main
import (
"strings"
)
var variableCompile = makeRegex(`([a-zA-Z_])([a-zA-Z0-9_])*`)
var blockedVariableNames = map[string]bool{
"if": true,
"else": true,
"elif": true,
"while": true,
"for": true,
"break": true,
"continue": true,
"return": true,
"let": true,
"import": true,
"from": true,
"do": true,
}
type variableValue struct {
VAL any
EXISTS any
origin string
}
type accessVariable struct {
name string
line int
code string
path string
}
func isVariable(code UNPARSEcode) bool {
return variableCompile.MatchString(code.code)
}
func parseVariable(code UNPARSEcode) (accessVariable, bool, ArErr, int) {
name := strings.TrimSpace(code.code)
if blockedVariableNames[name] {
return accessVariable{}, false, ArErr{"Naming Error", "Naming Error: \"" + name + "\" is a reserved keyword", code.line, code.path, code.realcode, true}, 1
}
return accessVariable{name: name, code: code.code, line: code.line}, true, ArErr{}, 1
}
func readVariable(v accessVariable, stack []map[string]variableValue) (any, ArErr) {
for i := len(stack) - 1; i >= 0; i-- {
if val, ok := stack[i][v.name]; ok {
return val.VAL, ArErr{}
}
}
return nil, ArErr{"Runtime Error", "variable \"" + v.name + "\" does not exist", v.line, v.path, v.code, true}
}

27
test.ar
View File

@@ -1,26 +1 @@
0x1
0x2
0x3
0x4
0x5
0x6
0x7
0x8
0x9
0xA
0xB
0xC
0xD
0xE
0xF
0x10
0x11
0x12
0x13
0x14
0x15
0x16
0x17
0x18
0x19
0x1A
log(mult(PI,PI, 2,4,34,5465))