mirror of
https://github.com/Open-Argon/argon-v3.git
synced 2025-12-06 00:46:07 +00:00
Start supporting numbers and strings
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@@ -1,2 +1,2 @@
|
|||||||
node_modules
|
node_modules
|
||||||
build
|
bin
|
||||||
47
readme.md
47
readme.md
@@ -1,11 +1,48 @@
|
|||||||
# Argon
|
<div align="center">
|
||||||
|
<p>
|
||||||
|
<img width="80" src="https://raw.githubusercontent.com/Ugric/Argon/main/logo.png">
|
||||||
|
</p>
|
||||||
|
<h1>Argon 3</h1>
|
||||||
|
</div>
|
||||||
|
|
||||||
The go to language for mathematicians!
|
ARGON 3 is a math-driven programming language designed to make code easy to read and write. It's not meant to be fast, as it's interpreted. This specification should be used as a guideline, and is subject to change for later versions. Later updates for Argon 3 should be backwards compatible (where possible) with code designed for older versions of the interpreter.
|
||||||
|
|
||||||
# Read Me
|
## 📚 Features
|
||||||
|
|
||||||
due to the project being in very early stages, the readme docs file is not yet being worked on. [read the specification to get an understanding of how the language will work.](spec.md)
|
- 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.
|
||||||
|
- 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.
|
||||||
|
- Lightweight: The Argon 3 interpreter is small and doesn't require a lot of system resources to run.
|
||||||
|
|
||||||
# Licence
|
## 💻 Installation
|
||||||
|
As of now, Argon 3 does not have an installer. Feel free to clone this repo and run the `build` file for your plateform. the build will be found in `bin/Argon-v3(.exe)`.
|
||||||
|
|
||||||
|
## 📖 Usage
|
||||||
|
|
||||||
|
To use Argon 3, you can create a file with the .ar extension and write your code in it. Then, you can run your code using the interpreter. For example, if you have a file called example.ar, you can run it using the following command:
|
||||||
|
|
||||||
|
```
|
||||||
|
argon example.ar
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🔍 Specification
|
||||||
|
|
||||||
|
For a detailed specification of the Argon 3 language, please refer to [spec.md](spec.md).
|
||||||
|
|
||||||
|
## 🚀 Example Code
|
||||||
|
|
||||||
|
Here's an example of how to define a function in Argon 3:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
f(x) = x^2 + 2*x + 1
|
||||||
|
log('f(10) =', f(10))
|
||||||
|
```
|
||||||
|
|
||||||
|
This code defines a function f(x) that calculates x^2 + 2*x + 1. It then calls the function with an argument of 10 and logs the result to the console.
|
||||||
|
|
||||||
|
Please note that this example is subject to change as the specification is in beta and may be updated frequently.
|
||||||
|
|
||||||
|
## Licence
|
||||||
|
|
||||||
MIT
|
MIT
|
||||||
|
|||||||
5
run.bat
Normal file
5
run.bat
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
@echo off
|
||||||
|
|
||||||
|
:: run the go run command passing the path to the main.go file, with the working directory set to the bin folder. pass in the arguments
|
||||||
|
|
||||||
|
go run ./src %*
|
||||||
51
spec.md
51
spec.md
@@ -24,10 +24,10 @@ reused variables, and infomation for use in understanding the pseudo REGEX:
|
|||||||
|
|
||||||
## set variable
|
## set variable
|
||||||
|
|
||||||
`(let/const or nothing) {NAME} = {ANY}`
|
`(let or nothing) {NAME} = {ANY}`
|
||||||
|
|
||||||
let and const variables will set variables. if a const is already set in that stack, it will throw an error.
|
let variables will set variables. at the end of a opperation (e.g. if, while, or function) drop the
|
||||||
at the end of a opperation (e.g. if, while, or function) drop the variable stack.
|
variable stack.
|
||||||
|
|
||||||
having no verb at the start suggests the program would like to edit a variables from a different stack.
|
having no verb at the start suggests the program would like to edit a variables from a different stack.
|
||||||
if there is no variable found in the other stacks, then it sets one in the current stack as a let.
|
if there is no variable found in the other stacks, then it sets one in the current stack as a let.
|
||||||
@@ -36,17 +36,16 @@ setting variables returns the value, which can be used.
|
|||||||
|
|
||||||
example:
|
example:
|
||||||
|
|
||||||
```
|
```javascript
|
||||||
if (x = 10) > 5 [
|
if (x = 10) > 5 do
|
||||||
log(x, 'is bigger than 5')
|
log(x, 'is bigger than 5')
|
||||||
]
|
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## functions
|
## functions
|
||||||
|
|
||||||
`(let/const or nothing) {NAME}({PARAMS}) = {CODE}`
|
`(let or nothing) {NAME}({PARAMS}) = {CODE}`
|
||||||
|
|
||||||
the starting verb follows the rules set by [set variable](#set-variable).
|
the starting verb follows the rules set by [set variable](#set-variable).
|
||||||
|
|
||||||
@@ -54,41 +53,41 @@ function can be called by using its name followed by brackets with the params.
|
|||||||
|
|
||||||
example:
|
example:
|
||||||
|
|
||||||
```
|
```javascript
|
||||||
|
f(x) = x^2 + 2*x + 1
|
||||||
const f(x) = x^2 + 2*x + 1
|
|
||||||
log('f(10) =', f(10))
|
log('f(10) =', f(10))
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
output:
|
output:
|
||||||
|
|
||||||
```
|
```javascript
|
||||||
|
|
||||||
f(10) = 121
|
f(10) = 121
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
if the function does not return, then the value given is unknown/null
|
if the function does not return, then the value returned is `unknown`
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## wrap
|
## wrap
|
||||||
|
|
||||||
`[{CODE}]`
|
```
|
||||||
|
do
|
||||||
|
{CODE}
|
||||||
|
```
|
||||||
|
|
||||||
a wrap encloses code in square brackets. its used to create a new scope, so variables set from
|
a wrap encloses code indented in after the word `do` its used to create a new scope, so variables set from
|
||||||
inside the wraps scope are deleted once the wrap is finished.
|
inside the wraps scope are deleted once the wrap is finished.
|
||||||
|
|
||||||
example:
|
example:
|
||||||
|
|
||||||
```
|
```javascript
|
||||||
let name = unknown
|
let name = unknown
|
||||||
[
|
|
||||||
|
do
|
||||||
name = input('name: ')
|
name = input('name: ')
|
||||||
let age = input('age: ')
|
let age = input('age: ')
|
||||||
log('you are', age, 'years old!')
|
log('you are', age, 'years old!')
|
||||||
]
|
|
||||||
log('hello', name)
|
log('hello', name)
|
||||||
log('we do not know your age anymore because it got deleted when the wrap finished.')
|
log('we do not know your age anymore because it got deleted when the wrap finished.')
|
||||||
```
|
```
|
||||||
@@ -97,17 +96,19 @@ A wrap, unless specificifed otherwise, can have a return value. This value can b
|
|||||||
|
|
||||||
example:
|
example:
|
||||||
|
|
||||||
```
|
```javascript
|
||||||
const password = [
|
let password = do
|
||||||
let password = input("set password: ")
|
let password = input("set password: ")
|
||||||
while len(password) < 8 [
|
while len(password) < 8 do
|
||||||
log("password must be longer then 8 characters!")
|
log("password must be longer then 8 characters!")
|
||||||
password = input("set password: ")
|
password = input("set password: ")
|
||||||
]
|
|
||||||
return password
|
return password
|
||||||
]
|
|
||||||
|
|
||||||
log("your password is", password)
|
log("your password is", password)
|
||||||
```
|
```
|
||||||
|
|
||||||
If the wrap does not take a return value, then the wrap passes the return value back to a parent wrap.
|
If the wrap does not take a return value, then the wrap passes the return value back to a parent wrap.
|
||||||
|
|
||||||
|
## Comments
|
||||||
|
`//{COMMENT}`
|
||||||
|
Comments allow the programmer to write a message into their code, without the message being processed by the computer.
|
||||||
7
src/comment.go
Normal file
7
src/comment.go
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
var commentCompile = makeRegex("( *)//.*")
|
||||||
|
|
||||||
|
func isComment(code UNPARSEcode) bool {
|
||||||
|
return commentCompile.MatchString(code.code)
|
||||||
|
}
|
||||||
102
src/import.go
Normal file
102
src/import.go
Normal file
@@ -0,0 +1,102 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"errors"
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
)
|
||||||
|
|
||||||
|
func FileExists(filename string) bool {
|
||||||
|
if _, err := os.Stat(filename); err == nil {
|
||||||
|
return true
|
||||||
|
|
||||||
|
} else if errors.Is(err, os.ErrNotExist) {
|
||||||
|
return false
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func readFile(path string) []UNPARSEcode {
|
||||||
|
file, err := os.Open(path)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
defer file.Close()
|
||||||
|
|
||||||
|
scanner := bufio.NewScanner(file)
|
||||||
|
// optionally, resize scanner's capacity for lines over 64K, see next example
|
||||||
|
output := []UNPARSEcode{}
|
||||||
|
line := 1
|
||||||
|
for scanner.Scan() {
|
||||||
|
output = append(output, UNPARSEcode{scanner.Text(), line})
|
||||||
|
line++
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := scanner.Err(); err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return output
|
||||||
|
}
|
||||||
|
|
||||||
|
func importMod(realpath string, origin string, main bool) string {
|
||||||
|
extention := filepath.Ext(realpath)
|
||||||
|
path := realpath
|
||||||
|
if extention == "" {
|
||||||
|
path += ".ar"
|
||||||
|
}
|
||||||
|
ex, err := os.Getwd()
|
||||||
|
if err != nil {
|
||||||
|
return err.Error()
|
||||||
|
}
|
||||||
|
executable, err := os.Executable()
|
||||||
|
if err != nil {
|
||||||
|
return err.Error()
|
||||||
|
}
|
||||||
|
executable = filepath.Dir(executable)
|
||||||
|
isABS := filepath.IsAbs(path)
|
||||||
|
var pathsToTest []string
|
||||||
|
if isABS {
|
||||||
|
pathsToTest = []string{
|
||||||
|
filepath.Join(path),
|
||||||
|
filepath.Join(realpath, "init.ar"),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
pathsToTest = []string{
|
||||||
|
filepath.Join(origin, realpath, "init.ar"),
|
||||||
|
filepath.Join(origin, path),
|
||||||
|
filepath.Join(origin, "modules", path),
|
||||||
|
filepath.Join(origin, "modules", realpath, "init.ar"),
|
||||||
|
filepath.Join(ex, path),
|
||||||
|
filepath.Join(ex, "modules", realpath, "init.ar"),
|
||||||
|
filepath.Join(ex, "modules", path),
|
||||||
|
filepath.Join(executable, "modules", realpath, "init.ar"),
|
||||||
|
filepath.Join(executable, "modules", path),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var p string
|
||||||
|
var found bool
|
||||||
|
for _, p = range pathsToTest {
|
||||||
|
if FileExists(p) {
|
||||||
|
found = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !found {
|
||||||
|
return "File does not exist: " + realpath
|
||||||
|
}
|
||||||
|
codelines := readFile(p)
|
||||||
|
|
||||||
|
translated, translationerr := translate(codelines)
|
||||||
|
if translationerr != "" {
|
||||||
|
return translationerr
|
||||||
|
}
|
||||||
|
run(translated)
|
||||||
|
return ""
|
||||||
|
}
|
||||||
21
src/main.go
21
src/main.go
@@ -1,8 +1,23 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import "fmt"
|
import (
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
|
||||||
|
// args without the program path
|
||||||
|
var Args = os.Args[1:]
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
translate("")
|
|
||||||
fmt.Println("hello world")
|
ex, e := os.Getwd()
|
||||||
|
if e != nil {
|
||||||
|
panic(e)
|
||||||
|
}
|
||||||
|
if len(Args) == 0 {
|
||||||
|
panic("No file specified")
|
||||||
|
}
|
||||||
|
err := importMod(Args[0], ex, true)
|
||||||
|
if err != "" {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ import (
|
|||||||
"strings"
|
"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]+)?)))?))( *)")
|
||||||
|
|
||||||
// a number type
|
// a number type
|
||||||
type number = *big.Rat
|
type number = *big.Rat
|
||||||
|
|
||||||
@@ -19,6 +21,10 @@ func stringToNumber(str string) (*big.Rat, bool) {
|
|||||||
return newNumber().SetString(str)
|
return newNumber().SetString(str)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func isNumber(code UNPARSEcode) bool {
|
||||||
|
return numberCompile.MatchString(code.code)
|
||||||
|
}
|
||||||
|
|
||||||
// converts a number type to a string
|
// converts a number type to a string
|
||||||
func numberToString(num number, fraction int) string {
|
func numberToString(num number, fraction int) string {
|
||||||
if fraction != 0 {
|
if fraction != 0 {
|
||||||
@@ -72,3 +78,12 @@ var subscript = map[byte]string{
|
|||||||
'8': "₈",
|
'8': "₈",
|
||||||
'9': "₉",
|
'9': "₉",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// returns translateNumber, success, error
|
||||||
|
func parseNumber(code UNPARSEcode) (translateNumber, bool, string) {
|
||||||
|
output, _ := newNumber().SetString(code.code)
|
||||||
|
return translateNumber{
|
||||||
|
number: output,
|
||||||
|
line: code.line,
|
||||||
|
}, true, ""
|
||||||
|
}
|
||||||
|
|||||||
14
src/regex.go
Normal file
14
src/regex.go
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"log"
|
||||||
|
"regexp"
|
||||||
|
)
|
||||||
|
|
||||||
|
func makeRegex(str string) *regexp.Regexp {
|
||||||
|
Compile, err := regexp.Compile("^(" + str + ")$")
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
return Compile
|
||||||
|
}
|
||||||
24
src/run.go
Normal file
24
src/run.go
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
func runLine(line any) (any, string) {
|
||||||
|
switch line.(type) {
|
||||||
|
case translateNumber:
|
||||||
|
return (numberToString(line.(translateNumber).number, 0)), ""
|
||||||
|
case translateString:
|
||||||
|
return (line.(translateString).str), ""
|
||||||
|
}
|
||||||
|
return nil, "Error: invalid code on line " + fmt.Sprint(line.(translateNumber).line) + ": " + line.(translateNumber).code
|
||||||
|
}
|
||||||
|
|
||||||
|
// returns error
|
||||||
|
func run(translated []any) (any, string) {
|
||||||
|
for _, val := range translated {
|
||||||
|
_, err := runLine(val)
|
||||||
|
if err != "" {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil, ""
|
||||||
|
}
|
||||||
42
src/string.go
Normal file
42
src/string.go
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
var stringCompile = makeRegex("(( *)\"((\\\\([a-z\\\"'`]))|[^\\\"])*\"( *))|(( *)'((\\\\([a-z\\'\"`]))|[^\\'])*'( *))")
|
||||||
|
|
||||||
|
func isString(code UNPARSEcode) bool {
|
||||||
|
return stringCompile.MatchString(code.code)
|
||||||
|
}
|
||||||
|
|
||||||
|
func unquoted(
|
||||||
|
str string,
|
||||||
|
) (string, error) {
|
||||||
|
str = strings.Trim(str, " ")
|
||||||
|
if str[0] == '\'' {
|
||||||
|
str = strings.Replace(str, "\\\"", "\"", -1)
|
||||||
|
str = strings.Replace(str, "\"", "\\\"", -1)
|
||||||
|
}
|
||||||
|
str = str[1 : len(str)-1]
|
||||||
|
str = strings.Replace(str, "\\'", "'", -1)
|
||||||
|
str = "\"" + str + "\""
|
||||||
|
return strconv.Unquote(str)
|
||||||
|
}
|
||||||
|
|
||||||
|
// returns translateString, success, error
|
||||||
|
func parseString(code UNPARSEcode) (translateString, bool, string) {
|
||||||
|
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{
|
||||||
|
str: unquoted,
|
||||||
|
line: code.line,
|
||||||
|
}, true, ""
|
||||||
|
}
|
||||||
@@ -2,9 +2,42 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"log"
|
||||||
)
|
)
|
||||||
|
|
||||||
func translate(code string) {
|
// returns (translateNumber | translateString), success, error
|
||||||
output, _ := newNumber().SetString("3.1415")
|
func translateVal(code UNPARSEcode, index int, codelines []UNPARSEcode, isLine bool) (any, bool, string) {
|
||||||
fmt.Println(numberToString(output, 0))
|
if isLine {
|
||||||
|
if isComment(code) {
|
||||||
|
return nil, true, ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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, ""
|
||||||
|
}
|
||||||
|
|
||||||
|
// returns [](translateNumber | translateString), error
|
||||||
|
func translate(codelines []UNPARSEcode) ([]any, string) {
|
||||||
|
translated := []any{}
|
||||||
|
for i, code := range codelines {
|
||||||
|
val, _, err := translateVal(code, i, codelines, true)
|
||||||
|
|
||||||
|
if err != "" {
|
||||||
|
log.Fatal(err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if val == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
translated = append(translated, val)
|
||||||
|
}
|
||||||
|
return translated, ""
|
||||||
}
|
}
|
||||||
|
|||||||
18
src/types.go
Normal file
18
src/types.go
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
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
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user