Improved performance

This commit is contained in:
Eduard Urbach 2024-08-01 23:41:39 +02:00
parent 3c70529015
commit 778c125d19
Signed by: akyoto
GPG Key ID: C874F672B1AF20C0
10 changed files with 112 additions and 124 deletions

View File

@ -11,8 +11,8 @@ import (
// Compile waits for the scan to finish and compiles all functions. // Compile waits for the scan to finish and compiles all functions.
func Compile(files <-chan *fs.File, functions <-chan *core.Function, errs <-chan error) (Result, error) { func Compile(files <-chan *fs.File, functions <-chan *core.Function, errs <-chan error) (Result, error) {
result := Result{} result := Result{}
allFiles := make([]*fs.File, 0, 8)
allFunctions := map[string]*core.Function{} allFunctions := map[string]*core.Function{}
allFiles := map[string]*fs.File{}
for functions != nil || files != nil || errs != nil { for functions != nil || files != nil || errs != nil {
select { select {
@ -31,7 +31,7 @@ func Compile(files <-chan *fs.File, functions <-chan *core.Function, errs <-chan
continue continue
} }
allFiles[file.Path] = file allFiles = append(allFiles, file)
case err, ok := <-errs: case err, ok := <-errs:
if !ok { if !ok {

View File

@ -23,7 +23,4 @@ var (
// Skips writing the executable to disk. // Skips writing the executable to disk.
Dry = false Dry = false
// Skips compiling assert statements.
SkipAsserts = false
) )

View File

@ -5,15 +5,10 @@ import (
"git.akyoto.dev/cli/q/src/build/asm" "git.akyoto.dev/cli/q/src/build/asm"
"git.akyoto.dev/cli/q/src/build/ast" "git.akyoto.dev/cli/q/src/build/ast"
"git.akyoto.dev/cli/q/src/build/config"
) )
// CompileAssert compiles an assertion. // CompileAssert compiles an assertion.
func (f *Function) CompileAssert(assert *ast.Assert) error { func (f *Function) CompileAssert(assert *ast.Assert) error {
if config.SkipAsserts {
return nil
}
f.count.assert++ f.count.assert++
success := fmt.Sprintf("%s_assert_%d_true", f.Name, f.count.assert) success := fmt.Sprintf("%s_assert_%d_true", f.Name, f.count.assert)
fail := fmt.Sprintf("%s_assert_%d_false", f.Name, f.count.assert) fail := fmt.Sprintf("%s_assert_%d_false", f.Name, f.count.assert)

View File

@ -15,7 +15,7 @@ type Operator struct {
// Operators defines the operators used in the language. // Operators defines the operators used in the language.
// The number corresponds to the operator priority and can not be zero. // The number corresponds to the operator priority and can not be zero.
var Operators = map[token.Kind]*Operator{ var Operators = [64]Operator{
token.Period: {".", 13, 2}, token.Period: {".", 13, 2},
token.Call: {"λ", 12, 1}, token.Call: {"λ", 12, 1},
token.Array: {"@", 12, 2}, token.Array: {"@", 12, 2},
@ -41,12 +41,15 @@ var Operators = map[token.Kind]*Operator{
token.LogicalAnd: {"&&", 2, 2}, token.LogicalAnd: {"&&", 2, 2},
token.LogicalOr: {"||", 1, 2}, token.LogicalOr: {"||", 1, 2},
token.Separator: {",", 0, 2},
token.Assign: {"=", math.MinInt8, 2}, token.Assign: {"=", math.MinInt8, 2},
token.Define: {":=", math.MinInt8, 2}, token.Define: {":=", math.MinInt8, 2},
token.AddAssign: {"+=", math.MinInt8, 2}, token.AddAssign: {"+=", math.MinInt8, 2},
token.SubAssign: {"-=", math.MinInt8, 2}, token.SubAssign: {"-=", math.MinInt8, 2},
token.MulAssign: {"*=", math.MinInt8, 2}, token.MulAssign: {"*=", math.MinInt8, 2},
token.DivAssign: {"/=", math.MinInt8, 2}, token.DivAssign: {"/=", math.MinInt8, 2},
token.ModAssign: {"%=", math.MinInt8, 2},
token.ShrAssign: {">>=", math.MinInt8, 2}, token.ShrAssign: {">>=", math.MinInt8, 2},
token.ShlAssign: {"<<=", math.MinInt8, 2}, token.ShlAssign: {"<<=", math.MinInt8, 2},
} }
@ -68,21 +71,9 @@ func isComplete(expr *Expression) bool {
} }
func numOperands(symbol token.Kind) int { func numOperands(symbol token.Kind) int {
operator, exists := Operators[symbol] return int(Operators[symbol].Operands)
if !exists {
return -1
}
return int(operator.Operands)
} }
func precedence(symbol token.Kind) int8 { func precedence(symbol token.Kind) int8 {
operator, exists := Operators[symbol] return Operators[symbol].Precedence
if !exists {
return -1
}
return operator.Precedence
} }

View File

@ -101,7 +101,10 @@ func Parse(tokens []token.Token) *Expression {
continue continue
} }
if t.IsOperator() { if !t.IsOperator() {
continue
}
if cursor == nil { if cursor == nil {
cursor = NewLeaf(t) cursor = NewLeaf(t)
cursor.Precedence = precedence(t.Kind) cursor.Precedence = precedence(t.Kind)
@ -156,8 +159,6 @@ func Parse(tokens []token.Token) *Expression {
} }
cursor = node cursor = node
continue
}
} }
return root return root

View File

@ -6,6 +6,7 @@ import (
"git.akyoto.dev/cli/q/src/build/token" "git.akyoto.dev/cli/q/src/build/token"
) )
// Stack is a stack of scopes.
type Stack struct { type Stack struct {
Scopes []*Scope Scopes []*Scope
} }

View File

@ -18,14 +18,6 @@ const (
BlockEnd // } BlockEnd // }
ArrayStart // [ ArrayStart // [
ArrayEnd // ] ArrayEnd // ]
_keywords // <keywords>
Assert // assert
Else // else
If // if
Import // import
Loop // loop
Return // return
_keywordsEnd // </keywords>
_operators // <operators> _operators // <operators>
Add // + Add // +
Sub // - Sub // -
@ -68,4 +60,12 @@ const (
ShrAssign // >>= ShrAssign // >>=
_assignmentsEnd // </assignments> _assignmentsEnd // </assignments>
_operatorsEnd // </operators> _operatorsEnd // </operators>
_keywords // <keywords>
Assert // assert
Else // else
If // if
Import // import
Loop // loop
Return // return
_keywordsEnd // </keywords>
) )

View File

@ -25,11 +25,15 @@ func TestFunction(t *testing.T) {
} }
func TestKeyword(t *testing.T) { func TestKeyword(t *testing.T) {
tokens := token.Tokenize([]byte("return x")) tokens := token.Tokenize([]byte("assert if import else loop return"))
expected := []token.Kind{ expected := []token.Kind{
token.Assert,
token.If,
token.Import,
token.Else,
token.Loop,
token.Return, token.Return,
token.Identifier,
token.EOF, token.EOF,
} }
@ -103,6 +107,37 @@ func TestOperator(t *testing.T) {
} }
} }
func TestOperatorAssign(t *testing.T) {
tokens := token.Tokenize([]byte(`a += b -= c *= d /= e &= f |= g ^= h <<= i >>= j`))
expected := []token.Kind{
token.Identifier,
token.AddAssign,
token.Identifier,
token.SubAssign,
token.Identifier,
token.MulAssign,
token.Identifier,
token.DivAssign,
token.Identifier,
token.AndAssign,
token.Identifier,
token.OrAssign,
token.Identifier,
token.XorAssign,
token.Identifier,
token.ShlAssign,
token.Identifier,
token.ShrAssign,
token.Identifier,
token.EOF,
}
for i, kind := range expected {
assert.Equal(t, tokens[i].Kind, kind)
}
}
func TestNegateFirstToken(t *testing.T) { func TestNegateFirstToken(t *testing.T) {
tokens := token.Tokenize([]byte(`-a`)) tokens := token.Tokenize([]byte(`-a`))
@ -244,37 +279,6 @@ func TestLeadingZero(t *testing.T) {
} }
} }
func TestOperatorAssign(t *testing.T) {
tokens := token.Tokenize([]byte(`a += b -= c *= d /= e &= f |= g ^= h <<= i >>= j`))
expected := []token.Kind{
token.Identifier,
token.AddAssign,
token.Identifier,
token.SubAssign,
token.Identifier,
token.MulAssign,
token.Identifier,
token.DivAssign,
token.Identifier,
token.AndAssign,
token.Identifier,
token.OrAssign,
token.Identifier,
token.XorAssign,
token.Identifier,
token.ShlAssign,
token.Identifier,
token.ShrAssign,
token.Identifier,
token.EOF,
}
for i, kind := range expected {
assert.Equal(t, tokens[i].Kind, kind)
}
}
func TestSeparator(t *testing.T) { func TestSeparator(t *testing.T) {
tokens := token.Tokenize([]byte("a,b,c")) tokens := token.Tokenize([]byte("a,b,c"))

View File

@ -33,9 +33,9 @@ func Run(args []string) int {
if err != nil { if err != nil {
fmt.Fprintln(os.Stderr, err) fmt.Fprintln(os.Stderr, err)
switch err.(type) { switch err := err.(type) {
case *exec.ExitError: case *exec.ExitError:
return 0 return err.ExitCode()
default: default:
return 1 return 1

View File

@ -18,6 +18,5 @@ func System(args []string) int {
fmt.Printf(line, "Compiler:", config.Executable) fmt.Printf(line, "Compiler:", config.Executable)
fmt.Printf(line, "Library:", config.Library) fmt.Printf(line, "Library:", config.Library)
fmt.Printf(line, "Threads:", strconv.Itoa(runtime.NumCPU())) fmt.Printf(line, "Threads:", strconv.Itoa(runtime.NumCPU()))
return 0 return 0
} }