Implemented echo example
This commit is contained in:
parent
b34470a97d
commit
824efbf424
18
examples/echo/echo.q
Normal file
18
examples/echo/echo.q
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
import mem
|
||||||
|
import sys
|
||||||
|
|
||||||
|
main() {
|
||||||
|
length := 4096
|
||||||
|
address := mem.alloc(length)
|
||||||
|
|
||||||
|
loop {
|
||||||
|
n := sys.read(0, address, length)
|
||||||
|
|
||||||
|
if n <= 0 {
|
||||||
|
mem.free(address, length)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
sys.write(1, address, n)
|
||||||
|
}
|
||||||
|
}
|
9
lib/mem/alloc.q
Normal file
9
lib/mem/alloc.q
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
import sys
|
||||||
|
|
||||||
|
alloc(length) {
|
||||||
|
return sys.mmap(0, length, 3, 290)
|
||||||
|
}
|
||||||
|
|
||||||
|
free(address, length) {
|
||||||
|
return sys.munmap(address, length)
|
||||||
|
}
|
@ -3,7 +3,7 @@ read(fd, address, length) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
write(fd, address, length) {
|
write(fd, address, length) {
|
||||||
syscall(1, fd, address, length)
|
return syscall(1, fd, address, length)
|
||||||
}
|
}
|
||||||
|
|
||||||
open(file, flags, mode) {
|
open(file, flags, mode) {
|
||||||
|
@ -22,21 +22,7 @@ func (f *Function) CompileDefinition(node *ast.Define) error {
|
|||||||
return errors.New(&errors.UnusedVariable{Name: name}, f.File, node.Name.Position)
|
return errors.New(&errors.UnusedVariable{Name: name}, f.File, node.Name.Position)
|
||||||
}
|
}
|
||||||
|
|
||||||
value := node.Value
|
return f.storeVariableInRegister(name, node.Value, uses)
|
||||||
|
|
||||||
err := value.EachLeaf(func(leaf *expression.Expression) error {
|
|
||||||
if leaf.Token.Kind == token.Identifier && !f.identifierExists(leaf.Token.Text()) {
|
|
||||||
return errors.New(&errors.UnknownIdentifier{Name: leaf.Token.Text()}, f.File, leaf.Token.Position)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return f.storeVariableInRegister(name, value, uses)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *Function) AddVariable(variable *Variable) {
|
func (f *Function) AddVariable(variable *Variable) {
|
||||||
@ -94,12 +80,7 @@ func (f *Function) identifierExists(name string) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (f *Function) storeVariableInRegister(name string, value *expression.Expression, uses int) error {
|
func (f *Function) storeVariableInRegister(name string, value *expression.Expression, uses int) error {
|
||||||
reg, exists := f.Scope().FindFree(f.cpu.General)
|
reg := f.Scope().MustFindFree(f.cpu.General)
|
||||||
|
|
||||||
if !exists {
|
|
||||||
panic("no free registers")
|
|
||||||
}
|
|
||||||
|
|
||||||
f.Scope().Reserve(reg)
|
f.Scope().Reserve(reg)
|
||||||
err := f.ExpressionToRegister(value, reg)
|
err := f.ExpressionToRegister(value, reg)
|
||||||
|
|
||||||
|
@ -1,7 +1,3 @@
|
|||||||
main() {
|
main() {
|
||||||
x := 1 + f(x)
|
x := 1 + f(x)
|
||||||
}
|
}
|
||||||
|
|
||||||
f(x) {
|
|
||||||
return x
|
|
||||||
}
|
|
@ -1,3 +1,7 @@
|
|||||||
main() {
|
main() {
|
||||||
x := 1 + f(x)
|
x := 1 + f(x)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
f(x) {
|
||||||
|
return x
|
||||||
|
}
|
@ -34,10 +34,10 @@ var errs = []struct {
|
|||||||
{"MissingOperand2.q", errors.MissingOperand},
|
{"MissingOperand2.q", errors.MissingOperand},
|
||||||
{"VariableAlreadyExists.q", &errors.VariableAlreadyExists{Name: "x"}},
|
{"VariableAlreadyExists.q", &errors.VariableAlreadyExists{Name: "x"}},
|
||||||
{"UnknownFunction.q", &errors.UnknownFunction{Name: "unknown"}},
|
{"UnknownFunction.q", &errors.UnknownFunction{Name: "unknown"}},
|
||||||
|
{"UnknownFunction2.q", &errors.UnknownFunction{Name: "f"}},
|
||||||
{"UnknownIdentifier.q", &errors.UnknownIdentifier{Name: "x"}},
|
{"UnknownIdentifier.q", &errors.UnknownIdentifier{Name: "x"}},
|
||||||
{"UnknownIdentifier2.q", &errors.UnknownIdentifier{Name: "x"}},
|
{"UnknownIdentifier2.q", &errors.UnknownIdentifier{Name: "x"}},
|
||||||
{"UnknownIdentifier3.q", &errors.UnknownIdentifier{Name: "f"}},
|
{"UnknownIdentifier3.q", &errors.UnknownIdentifier{Name: "x"}},
|
||||||
{"UnknownIdentifier4.q", &errors.UnknownIdentifier{Name: "x"}},
|
|
||||||
{"UnusedVariable.q", &errors.UnusedVariable{Name: "x"}},
|
{"UnusedVariable.q", &errors.UnusedVariable{Name: "x"}},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,18 +10,19 @@ import (
|
|||||||
|
|
||||||
var examples = []struct {
|
var examples = []struct {
|
||||||
Name string
|
Name string
|
||||||
ExpectedOutput string
|
Input string
|
||||||
ExpectedExitCode int
|
Output string
|
||||||
|
ExitCode int
|
||||||
}{
|
}{
|
||||||
{"hello", "Hello", 0},
|
{"hello", "", "Hello", 0},
|
||||||
{"factorial", "", 120},
|
{"factorial", "", "", 120},
|
||||||
{"fibonacci", "", 55},
|
{"fibonacci", "", "", 55},
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestExamples(t *testing.T) {
|
func TestExamples(t *testing.T) {
|
||||||
for _, test := range examples {
|
for _, test := range examples {
|
||||||
t.Run(test.Name, func(t *testing.T) {
|
t.Run(test.Name, func(t *testing.T) {
|
||||||
run(t, filepath.Join("..", "examples", test.Name), test.ExpectedOutput, test.ExpectedExitCode)
|
run(t, filepath.Join("..", "examples", test.Name), test.Input, test.Output, test.ExitCode)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"git.akyoto.dev/cli/q/src/build"
|
"git.akyoto.dev/cli/q/src/build"
|
||||||
@ -12,33 +13,34 @@ import (
|
|||||||
|
|
||||||
var programs = []struct {
|
var programs = []struct {
|
||||||
Name string
|
Name string
|
||||||
ExpectedOutput string
|
Input string
|
||||||
ExpectedExitCode int
|
Output string
|
||||||
|
ExitCode int
|
||||||
}{
|
}{
|
||||||
{"empty", "", 0},
|
{"empty", "", "", 0},
|
||||||
{"math", "", 10},
|
{"math", "", "", 10},
|
||||||
{"precedence", "", 10},
|
{"precedence", "", "", 10},
|
||||||
{"square-sum", "", 25},
|
{"square-sum", "", "", 25},
|
||||||
{"chained-calls", "", 9},
|
{"chained-calls", "", "", 9},
|
||||||
{"nested-calls", "", 4},
|
{"nested-calls", "", "", 4},
|
||||||
{"param", "", 3},
|
{"param", "", "", 3},
|
||||||
{"param-multi", "", 21},
|
{"param-multi", "", "", 21},
|
||||||
{"reuse", "", 3},
|
{"reuse", "", "", 3},
|
||||||
{"return", "", 6},
|
{"return", "", "", 6},
|
||||||
{"reassign", "", 2},
|
{"reassign", "", "", 2},
|
||||||
{"branch", "", 0},
|
{"branch", "", "", 0},
|
||||||
{"branch-and", "", 0},
|
{"branch-and", "", "", 0},
|
||||||
{"branch-or", "", 0},
|
{"branch-or", "", "", 0},
|
||||||
{"branch-both", "", 0},
|
{"branch-both", "", "", 0},
|
||||||
{"jump-near", "", 0},
|
{"jump-near", "", "", 0},
|
||||||
{"loop", "", 0},
|
{"loop", "", "", 0},
|
||||||
{"loop-lifetime", "", 0},
|
{"loop-lifetime", "", "", 0},
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestPrograms(t *testing.T) {
|
func TestPrograms(t *testing.T) {
|
||||||
for _, test := range programs {
|
for _, test := range programs {
|
||||||
t.Run(test.Name, func(t *testing.T) {
|
t.Run(test.Name, func(t *testing.T) {
|
||||||
run(t, filepath.Join("programs", test.Name+".q"), test.ExpectedOutput, test.ExpectedExitCode)
|
run(t, filepath.Join("programs", test.Name+".q"), test.Input, test.Output, test.ExitCode)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -57,7 +59,7 @@ func BenchmarkPrograms(b *testing.B) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// run builds and runs the file to check if the output matches the expected output.
|
// run builds and runs the file to check if the output matches the expected output.
|
||||||
func run(t *testing.T, name string, expectedOutput string, expectedExitCode int) {
|
func run(t *testing.T, name string, input string, expectedOutput string, expectedExitCode int) {
|
||||||
b := build.New(name)
|
b := build.New(name)
|
||||||
assert.True(t, len(b.Executable()) > 0)
|
assert.True(t, len(b.Executable()) > 0)
|
||||||
|
|
||||||
@ -72,6 +74,7 @@ func run(t *testing.T, name string, expectedOutput string, expectedExitCode int)
|
|||||||
assert.True(t, stat.Size() > 0)
|
assert.True(t, stat.Size() > 0)
|
||||||
|
|
||||||
cmd := exec.Command(b.Executable())
|
cmd := exec.Command(b.Executable())
|
||||||
|
cmd.Stdin = strings.NewReader(input)
|
||||||
output, err := cmd.Output()
|
output, err := cmd.Output()
|
||||||
exitCode := 0
|
exitCode := 0
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user