finish operators

This commit is contained in:
2023-03-08 23:41:33 +00:00
parent 09deba8912
commit 0892b78fd4
6 changed files with 177 additions and 28 deletions

View File

@@ -14,16 +14,18 @@ func isBlank(code UNPARSEcode) bool {
return strings.TrimSpace(code.code) == "" return strings.TrimSpace(code.code) == ""
} }
func parseComment(code UNPARSEcode, index int, codelines []UNPARSEcode) (any, bool, ArErr) { func parseComment(code UNPARSEcode, index int, codelines []UNPARSEcode) (any, bool, ArErr, int) {
split := strings.Split(code.code, "#") split := strings.Split(code.code, "#")
temp := []string{} temp := []string{}
step := 1
for i := 0; i < len(split)-1; i++ { for i := 0; i < len(split)-1; i++ {
temp = append(temp, split[i]) temp = append(temp, split[i])
joined := strings.Join(temp, "#") joined := strings.Join(temp, "#")
resp, worked, _, _ := translateVal(UNPARSEcode{code: joined, realcode: code.realcode, line: code.line, path: code.path}, index, codelines, true) resp, worked, _, s := translateVal(UNPARSEcode{code: joined, realcode: code.realcode, line: code.line, path: code.path}, index, codelines, true)
step += s - 1
if worked { if worked {
return resp, true, ArErr{} return resp, true, ArErr{}, step
} }
} }
return nil, false, ArErr{"Syntax Error", "invalid comment", code.line, code.path, code.realcode, true} return nil, false, ArErr{"Syntax Error", "invalid comment", code.line, code.path, code.realcode, true}, step
} }

View File

@@ -63,6 +63,8 @@ func numberToString(num number, fraction int, simplify bool) string {
floated := float64(int(divPI * 100)) floated := float64(int(divPI * 100))
if divPI == 1 { if divPI == 1 {
return "π" return "π"
} else if divPI == -1 {
return "-π"
} else if divPI == 0 { } else if divPI == 0 {
return "0" return "0"
} else if (divPI*100) == floated && floated != 0 { } else if (divPI*100) == floated && floated != 0 {

View File

@@ -2,6 +2,7 @@ package main
import ( import (
"fmt" "fmt"
"math"
"reflect" "reflect"
"strings" "strings"
) )
@@ -243,7 +244,7 @@ func calcNegative(o operationType, stack stack) (number, ArErr) {
return output, ArErr{} return output, ArErr{}
} }
func calcDiv(o operationType, stack stack) (number, ArErr) { func calcDivide(o operationType, stack stack) (number, ArErr) {
resp, err := runVal( resp, err := runVal(
o.values[0], o.values[0],
@@ -256,7 +257,7 @@ func calcDiv(o operationType, stack stack) (number, ArErr) {
if !isAnyNumber(resp) { if !isAnyNumber(resp) {
return nil, ArErr{ return nil, ArErr{
"Runtime Error", "Runtime Error",
"Cannot subtract from type '" + typeof(resp) + "'", "Cannot divide from type '" + typeof(resp) + "'",
o.line, o.line,
o.path, o.path,
o.code, o.code,
@@ -480,6 +481,107 @@ func equals(a any, b any) bool {
return reflect.DeepEqual(a, b) return reflect.DeepEqual(a, b)
} }
func calcMod(o operationType, stack stack) (number, ArErr) {
resp, err := runVal(
o.values[0],
stack,
)
resp = classVal(resp)
if err.EXISTS {
return nil, err
}
if !isAnyNumber(resp) {
return nil, ArErr{
"Runtime Error",
"Cannot calculate modulus from type '" + typeof(resp) + "'",
o.line,
o.path,
o.code,
true,
}
}
output := newNumber().Set(resp.(number))
for i := 1; i < len(o.values); i++ {
resp, err := runVal(
o.values[i],
stack,
)
resp = classVal(resp)
if err.EXISTS {
return nil, err
}
if typeof(resp) == "number" {
n1, _ := output.Float64()
n2, _ := resp.(number).Float64()
output = newNumber().SetFloat64(math.Mod(n1, n2))
} else {
return nil, ArErr{
"Runtime Error",
"Cannot calculate modulus of type '" + typeof(resp) + "'",
o.line,
o.path,
o.code,
true,
}
}
}
return output, ArErr{}
}
func calcIntDiv(o operationType, stack stack) (number, ArErr) {
resp, err := calcDivide(o, stack)
x, _ := resp.Float64()
resp = newNumber().SetFloat64(math.Trunc(x))
return resp, err
}
func calcPower(o operationType, stack stack) (number, ArErr) {
resp, err := runVal(
o.values[0],
stack,
)
resp = classVal(resp)
if err.EXISTS {
return nil, err
}
if typeof(resp) != "number" {
return nil, ArErr{
"Runtime Error",
"Cannot calculate power of type '" + typeof(resp) + "'",
o.line,
o.path,
o.code,
true,
}
}
output := newNumber().Set(resp.(number))
for i := 1; i < len(o.values); i++ {
resp, err := runVal(
o.values[i],
stack,
)
resp = classVal(resp)
if err.EXISTS {
return nil, err
}
if typeof(resp) == "number" {
n1, _ := output.Float64()
n2, _ := resp.(number).Float64()
output = newNumber().SetFloat64(math.Pow(n1, n2))
} else {
return nil, ArErr{
"Runtime Error",
"Cannot calculate power of type '" + typeof(resp) + "'",
o.line,
o.path,
o.code,
true,
}
}
}
return output, ArErr{}
}
func runOperation(o operationType, stack stack) (any, ArErr) { func runOperation(o operationType, stack stack) (any, ArErr) {
switch o.operation { switch o.operation {
case 0: case 0:
@@ -511,7 +613,13 @@ func runOperation(o operationType, stack stack) (any, ArErr) {
case 12: case 12:
return calcMul(o, stack) return calcMul(o, stack)
case 13: case 13:
return calcDiv(o, stack) return calcMod(o, stack)
case 14:
return calcIntDiv(o, stack)
case 15:
return calcDivide(o, stack)
case 16:
return calcPower(o, stack)
} }
panic("Unknown operation: " + fmt.Sprint(o.operation)) panic("Unknown operation: " + fmt.Sprint(o.operation))

View File

@@ -48,6 +48,8 @@ func runVal(line any, stack stack) (any, ArErr) {
return runVal(x.VAL, stack) return runVal(x.VAL, stack)
case operationType: case operationType:
return runOperation(x, stack) return runOperation(x, stack)
case ArDelete:
return runDelete(x, stack)
} }
fmt.Println("unreachable", reflect.TypeOf(line)) fmt.Println("unreachable", reflect.TypeOf(line))
panic("unreachable") panic("unreachable")

View File

@@ -13,10 +13,12 @@ func translateVal(code UNPARSEcode, index int, codelines []UNPARSEcode, isLine b
if isLine { if isLine {
if isBlank(code) { if isBlank(code) {
return nil, true, ArErr{}, 1 return nil, true, ArErr{}, 1
} else if isDeleteVariable(code) {
return parseDelete(code, index, codelines)
} else if isComment(code) { } else if isComment(code) {
resp, worked, err := parseComment(code, index, codelines) resp, worked, err, step := parseComment(code, index, codelines)
if worked { if worked {
return resp, worked, err, 1 return resp, worked, err, step
} }
} }
} }

View File

@@ -1,7 +1,6 @@
package main package main
import ( import (
"fmt"
"strings" "strings"
) )
@@ -9,7 +8,7 @@ var variableCompile = makeRegex(`( *)([a-zA-Z_]|(\p{L}\p{M}*))([a-zA-Z0-9_]|(\p{
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 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)+`) var setVariableCompile = makeRegex(`( *)(let( +))(.|\n)+( *)=(.|\n)+`)
var autoAsignVariableCompile = makeRegex(`(.|\n)+=(.|\n)+`) var autoAsignVariableCompile = makeRegex(`(.|\n)+=(.|\n)+`)
var deleteVariableCompile = makeRegex(`( *)delete( +)( *)`) var deleteVariableCompile = makeRegex(`( *)delete( +)(.|\n)+( *)`)
var blockedVariableNames = map[string]bool{ var blockedVariableNames = map[string]bool{
"if": true, "if": true,
@@ -53,6 +52,13 @@ type setFunction struct {
params []string params []string
} }
type ArDelete struct {
value any
line int
code string
path string
}
func isVariable(code UNPARSEcode) bool { func isVariable(code UNPARSEcode) bool {
return variableCompile.MatchString(code.code) return variableCompile.MatchString(code.code)
} }
@@ -92,9 +98,7 @@ func nameToTranslated(code UNPARSEcode, index int, lines []UNPARSEcode) (any, bo
params[i] = strings.TrimSpace(params[i]) params[i] = strings.TrimSpace(params[i])
} }
name := strings.TrimSpace(trimmed[:start]) name := strings.TrimSpace(trimmed[:start])
fmt.Println(name)
if blockedVariableNames[name] { if blockedVariableNames[name] {
fmt.Println(name)
return accessVariable{}, false, ArErr{"Naming Error", "\"" + name + "\" is a reserved keyword", code.line, code.path, code.realcode, true}, 1 return accessVariable{}, false, ArErr{"Naming Error", "\"" + name + "\" is a reserved keyword", code.line, code.path, code.realcode, true}, 1
} }
value, success, err, i := translateVal(UNPARSEcode{ value, success, err, i := translateVal(UNPARSEcode{
@@ -185,7 +189,7 @@ func setVariableValue(v setVariable, stack stack) (any, ArErr) {
if v.TYPE == "let" { if v.TYPE == "let" {
if _, ok := stack[len(stack)-1][v.toset.(accessVariable).name]; ok { if _, ok := stack[len(stack)-1][v.toset.(accessVariable).name]; ok {
return stack, 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}
} }
stack[len(stack)-1][v.toset.(accessVariable).name] = resp stack[len(stack)-1][v.toset.(accessVariable).name] = resp
} else { } else {
@@ -218,24 +222,53 @@ func setVariableValue(v setVariable, stack stack) (any, ArErr) {
return resp, ArErr{} return resp, ArErr{}
} }
/* func parseDelete(code UNPARSEcode, index int, lines []UNPARSEcode) (ArDelete, bool, ArErr, int) {
func parseAutosAsignVariable(code UNPARSEcode, index int, lines []UNPARSEcode) (setVariable, bool, ArErr, int) {
trim := strings.TrimSpace(code.code) trim := strings.TrimSpace(code.code)
equalsplit := strings.SplitN(trim, "=", 2) spacesplit := strings.SplitN(trim, " ", 2)
name := strings.TrimSpace(equalsplit[0]) name := strings.TrimSpace(spacesplit[1])
params := []string{}
function := false
if blockedVariableNames[name] { if blockedVariableNames[name] {
return setVariable{}, false, ArErr{"Naming Error", "\"" + name + "\" is a reserved keyword", code.line, code.path, code.realcode, true}, 1 return ArDelete{}, false, ArErr{"Naming Error", "\"" + name + "\" is a reserved keyword", code.line, code.path, code.realcode, true}, 1
} }
value, success, err, i := translateVal(UNPARSEcode{code: equalsplit[1], realcode: code.realcode, line: code.line, path: code.path}, index, lines, false) toset, success, err, i := translateVal(UNPARSEcode{code: name, realcode: code.realcode, line: code.line, path: code.path}, index, lines, false)
if !success { if !success {
return setVariable{}, false, err, i return ArDelete{}, false, err, i
} }
return setVariable{TYPE: "let", name: name, value: value, function: function, params: params, line: code.line, code: code.code, path: code.path}, true, ArErr{}, i return ArDelete{
toset,
code.line,
code.code,
code.path,
}, true, ArErr{}, i
} }
func runDelete(d ArDelete, stack stack) (any, ArErr) {
*/ switch x := d.value.(type) {
case accessVariable:
for i := len(stack) - 1; i >= 0; i-- {
if _, ok := stack[i][x.name]; ok {
delete(stack[i], x.name)
return nil, ArErr{}
}
}
return nil, ArErr{"Runtime Error", "variable \"" + x.name + "\" does not exist", d.line, d.path, d.code, true}
case ArMapGet:
respp, err := runVal(x.VAL, stack)
if err.EXISTS {
return nil, err
}
key, err := runVal(x.key, stack)
if err.EXISTS {
return nil, err
}
switch y := respp.(type) {
case ArMap:
delete(y, key)
default:
return nil, ArErr{"Runtime Error", "can't delete for non map", d.line, d.path, d.code, true}
}
default:
return nil, ArErr{"Runtime Error", "can't delete for non variable", d.line, d.path, d.code, true}
}
return nil, ArErr{}
}