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) {
|
||||
syscall(1, fd, address, length)
|
||||
return syscall(1, fd, address, length)
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
value := node.Value
|
||||
|
||||
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)
|
||||
return f.storeVariableInRegister(name, node.Value, uses)
|
||||
}
|
||||
|
||||
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 {
|
||||
reg, exists := f.Scope().FindFree(f.cpu.General)
|
||||
|
||||
if !exists {
|
||||
panic("no free registers")
|
||||
}
|
||||
|
||||
reg := f.Scope().MustFindFree(f.cpu.General)
|
||||
f.Scope().Reserve(reg)
|
||||
err := f.ExpressionToRegister(value, reg)
|
||||
|
||||
|
@ -1,7 +1,3 @@
|
||||
main() {
|
||||
x := 1 + f(x)
|
||||
}
|
||||
|
||||
f(x) {
|
||||
return x
|
||||
}
|
@ -1,3 +1,7 @@
|
||||
main() {
|
||||
x := 1 + f(x)
|
||||
}
|
||||
|
||||
f(x) {
|
||||
return x
|
||||
}
|
@ -34,10 +34,10 @@ var errs = []struct {
|
||||
{"MissingOperand2.q", errors.MissingOperand},
|
||||
{"VariableAlreadyExists.q", &errors.VariableAlreadyExists{Name: "x"}},
|
||||
{"UnknownFunction.q", &errors.UnknownFunction{Name: "unknown"}},
|
||||
{"UnknownFunction2.q", &errors.UnknownFunction{Name: "f"}},
|
||||
{"UnknownIdentifier.q", &errors.UnknownIdentifier{Name: "x"}},
|
||||
{"UnknownIdentifier2.q", &errors.UnknownIdentifier{Name: "x"}},
|
||||
{"UnknownIdentifier3.q", &errors.UnknownIdentifier{Name: "f"}},
|
||||
{"UnknownIdentifier4.q", &errors.UnknownIdentifier{Name: "x"}},
|
||||
{"UnknownIdentifier3.q", &errors.UnknownIdentifier{Name: "x"}},
|
||||
{"UnusedVariable.q", &errors.UnusedVariable{Name: "x"}},
|
||||
}
|
||||
|
||||
|
@ -9,19 +9,20 @@ import (
|
||||
)
|
||||
|
||||
var examples = []struct {
|
||||
Name string
|
||||
ExpectedOutput string
|
||||
ExpectedExitCode int
|
||||
Name string
|
||||
Input string
|
||||
Output string
|
||||
ExitCode int
|
||||
}{
|
||||
{"hello", "Hello", 0},
|
||||
{"factorial", "", 120},
|
||||
{"fibonacci", "", 55},
|
||||
{"hello", "", "Hello", 0},
|
||||
{"factorial", "", "", 120},
|
||||
{"fibonacci", "", "", 55},
|
||||
}
|
||||
|
||||
func TestExamples(t *testing.T) {
|
||||
for _, test := range examples {
|
||||
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/exec"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"git.akyoto.dev/cli/q/src/build"
|
||||
@ -11,34 +12,35 @@ import (
|
||||
)
|
||||
|
||||
var programs = []struct {
|
||||
Name string
|
||||
ExpectedOutput string
|
||||
ExpectedExitCode int
|
||||
Name string
|
||||
Input string
|
||||
Output string
|
||||
ExitCode int
|
||||
}{
|
||||
{"empty", "", 0},
|
||||
{"math", "", 10},
|
||||
{"precedence", "", 10},
|
||||
{"square-sum", "", 25},
|
||||
{"chained-calls", "", 9},
|
||||
{"nested-calls", "", 4},
|
||||
{"param", "", 3},
|
||||
{"param-multi", "", 21},
|
||||
{"reuse", "", 3},
|
||||
{"return", "", 6},
|
||||
{"reassign", "", 2},
|
||||
{"branch", "", 0},
|
||||
{"branch-and", "", 0},
|
||||
{"branch-or", "", 0},
|
||||
{"branch-both", "", 0},
|
||||
{"jump-near", "", 0},
|
||||
{"loop", "", 0},
|
||||
{"loop-lifetime", "", 0},
|
||||
{"empty", "", "", 0},
|
||||
{"math", "", "", 10},
|
||||
{"precedence", "", "", 10},
|
||||
{"square-sum", "", "", 25},
|
||||
{"chained-calls", "", "", 9},
|
||||
{"nested-calls", "", "", 4},
|
||||
{"param", "", "", 3},
|
||||
{"param-multi", "", "", 21},
|
||||
{"reuse", "", "", 3},
|
||||
{"return", "", "", 6},
|
||||
{"reassign", "", "", 2},
|
||||
{"branch", "", "", 0},
|
||||
{"branch-and", "", "", 0},
|
||||
{"branch-or", "", "", 0},
|
||||
{"branch-both", "", "", 0},
|
||||
{"jump-near", "", "", 0},
|
||||
{"loop", "", "", 0},
|
||||
{"loop-lifetime", "", "", 0},
|
||||
}
|
||||
|
||||
func TestPrograms(t *testing.T) {
|
||||
for _, test := range programs {
|
||||
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.
|
||||
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)
|
||||
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)
|
||||
|
||||
cmd := exec.Command(b.Executable())
|
||||
cmd.Stdin = strings.NewReader(input)
|
||||
output, err := cmd.Output()
|
||||
exitCode := 0
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user