Improved type system
This commit is contained in:
parent
7634244c56
commit
f19d9063a5
@ -10,5 +10,5 @@ main() {
|
|||||||
address[3] = 'l'
|
address[3] = 'l'
|
||||||
address[4] = 'o'
|
address[4] = 'o'
|
||||||
sys.write(1, address, length)
|
sys.write(1, address, length)
|
||||||
mem.free(address, length)
|
mem.free(address)
|
||||||
}
|
}
|
@ -9,7 +9,7 @@ main() {
|
|||||||
n := sys.read(0, address, length)
|
n := sys.read(0, address, length)
|
||||||
|
|
||||||
if n <= 0 {
|
if n <= 0 {
|
||||||
mem.free(address, length)
|
mem.free(address)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -30,5 +30,5 @@ print(p *Point) {
|
|||||||
out[6] = '0' + p.y
|
out[6] = '0' + p.y
|
||||||
out[7] = '\n'
|
out[7] = '\n'
|
||||||
sys.write(1, out, 8)
|
sys.write(1, out, 8)
|
||||||
mem.free(out, 8)
|
mem.free(out)
|
||||||
}
|
}
|
@ -6,10 +6,10 @@ number(x Int) {
|
|||||||
buffer := mem.alloc(length)
|
buffer := mem.alloc(length)
|
||||||
address, count := itoa(x, buffer, length)
|
address, count := itoa(x, buffer, length)
|
||||||
sys.write(1, address, count)
|
sys.write(1, address, count)
|
||||||
mem.free(buffer, length)
|
mem.free(buffer)
|
||||||
}
|
}
|
||||||
|
|
||||||
itoa(x Int, buffer Pointer, length Int) -> (Pointer, Int) {
|
itoa(x Int, buffer *Any, length Int) -> (*Any, Int) {
|
||||||
end := buffer + length
|
end := buffer + length
|
||||||
tmp := end
|
tmp := end
|
||||||
digit := 0
|
digit := 0
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import sys
|
import sys
|
||||||
|
|
||||||
free(address Pointer, length Int) -> Int {
|
free(address []Any) -> Int {
|
||||||
return sys.munmap(address-8, length+8)
|
return sys.munmap(address-8, len(address)+8)
|
||||||
}
|
}
|
@ -1,23 +1,23 @@
|
|||||||
getcwd(buffer Pointer, length Int) -> Int {
|
getcwd(buffer *Any, length Int) -> Int {
|
||||||
return syscall(79, buffer, length)
|
return syscall(79, buffer, length)
|
||||||
}
|
}
|
||||||
|
|
||||||
chdir(path Pointer) -> Int {
|
chdir(path *Any) -> Int {
|
||||||
return syscall(80, path)
|
return syscall(80, path)
|
||||||
}
|
}
|
||||||
|
|
||||||
rename(old Pointer, new Pointer) -> Int {
|
rename(old *Any, new *Any) -> Int {
|
||||||
return syscall(82, old, new)
|
return syscall(82, old, new)
|
||||||
}
|
}
|
||||||
|
|
||||||
mkdir(path Pointer, mode Int) -> Int {
|
mkdir(path *Any, mode Int) -> Int {
|
||||||
return syscall(83, path, mode)
|
return syscall(83, path, mode)
|
||||||
}
|
}
|
||||||
|
|
||||||
rmdir(path Pointer) -> Int {
|
rmdir(path *Any) -> Int {
|
||||||
return syscall(84, path)
|
return syscall(84, path)
|
||||||
}
|
}
|
||||||
|
|
||||||
unlink(file Pointer) -> Int {
|
unlink(file *Any) -> Int {
|
||||||
return syscall(87, file)
|
return syscall(87, file)
|
||||||
}
|
}
|
@ -1,13 +1,13 @@
|
|||||||
read(fd Int, address Pointer, length Int) -> Int {
|
read(fd Int, address *Any, length Int) -> Int {
|
||||||
return syscall(0, fd, address, length)
|
return syscall(0, fd, address, length)
|
||||||
}
|
}
|
||||||
|
|
||||||
write(fd Int, address Pointer, length Int) -> Int {
|
write(fd Int, address *Any, length Int) -> Int {
|
||||||
return syscall(1, fd, address, length)
|
return syscall(1, fd, address, length)
|
||||||
}
|
}
|
||||||
|
|
||||||
open(file Pointer, flags Int, mode Int) -> Int {
|
open(path *Any, flags Int, mode Int) -> Int {
|
||||||
return syscall(2, file, flags, mode)
|
return syscall(2, path, flags, mode)
|
||||||
}
|
}
|
||||||
|
|
||||||
close(fd Int) -> Int {
|
close(fd Int) -> Int {
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
read(fd Int, address Pointer, length Int) -> Int {
|
read(fd Int, address *Any, length Int) -> Int {
|
||||||
return syscall(0x2000003, fd, address, length)
|
return syscall(0x2000003, fd, address, length)
|
||||||
}
|
}
|
||||||
|
|
||||||
write(fd Int, address Pointer, length Int) -> Int {
|
write(fd Int, address *Any, length Int) -> Int {
|
||||||
return syscall(0x2000004, fd, address, length)
|
return syscall(0x2000004, fd, address, length)
|
||||||
}
|
}
|
||||||
|
|
||||||
open(file Pointer, flags Int, mode Int) -> Int {
|
open(path *Any, flags Int, mode Int) -> Int {
|
||||||
return syscall(0x2000005, file, flags, mode)
|
return syscall(0x2000005, path, flags, mode)
|
||||||
}
|
}
|
||||||
|
|
||||||
close(fd Int) -> Int {
|
close(fd Int) -> Int {
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
read(fd Int, address Pointer, length Int) -> Int {
|
read(fd Int, address *Any, length Int) -> Int {
|
||||||
kernel32.ReadFile(fd, address, length)
|
kernel32.ReadFile(fd, address, length)
|
||||||
return length
|
return length
|
||||||
}
|
}
|
||||||
|
|
||||||
write(fd Int, address Pointer, length Int) -> Int {
|
write(fd Int, address *Any, length Int) -> Int {
|
||||||
fd = kernel32.GetStdHandle(-10 - fd)
|
fd = kernel32.GetStdHandle(-10 - fd)
|
||||||
kernel32.WriteConsoleA(fd, address, length, 0)
|
kernel32.WriteConsoleA(fd, address, length, 0)
|
||||||
return length
|
return length
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
mmap(address Int, length Int, protection Int, flags Int) -> Pointer {
|
mmap(address Int, length Int, protection Int, flags Int) -> *Any {
|
||||||
return syscall(9, address, length, protection, flags)
|
return syscall(9, address, length, protection, flags)
|
||||||
}
|
}
|
||||||
|
|
||||||
munmap(address Pointer, length Int) -> Int {
|
munmap(address *Any, length Int) -> Int {
|
||||||
return syscall(11, address, length)
|
return syscall(11, address, length)
|
||||||
}
|
}
|
@ -1,7 +1,7 @@
|
|||||||
mmap(address Int, length Int, protection Int, flags Int) -> Pointer {
|
mmap(address Int, length Int, protection Int, flags Int) -> *Any {
|
||||||
return syscall(0x20000C5, address, length, protection, flags)
|
return syscall(0x20000C5, address, length, protection, flags)
|
||||||
}
|
}
|
||||||
|
|
||||||
munmap(address Pointer, length Int) -> Int {
|
munmap(address *Any, length Int) -> Int {
|
||||||
return syscall(0x2000049, address, length)
|
return syscall(0x2000049, address, length)
|
||||||
}
|
}
|
@ -1,7 +1,7 @@
|
|||||||
mmap(address Int, length Int, protection Int, flags Int) -> Pointer {
|
mmap(address Int, length Int, protection Int, flags Int) -> *Any {
|
||||||
return kernel32.VirtualAlloc(address, length, flags, protection)
|
return kernel32.VirtualAlloc(address, length, flags, protection)
|
||||||
}
|
}
|
||||||
|
|
||||||
munmap(address Pointer, length Int) -> Int {
|
munmap(address *Any, length Int) -> Int {
|
||||||
return kernel32.VirtualFree(address, length, 0x4000)
|
return kernel32.VirtualFree(address, length, 0x4000)
|
||||||
}
|
}
|
@ -9,7 +9,7 @@ socket(family Int, type Int, protocol Int) -> Int {
|
|||||||
return syscall(41, family, type, protocol)
|
return syscall(41, family, type, protocol)
|
||||||
}
|
}
|
||||||
|
|
||||||
accept(fd Int, address Pointer, length Int) -> Int {
|
accept(fd Int, address *Any, length Int) -> Int {
|
||||||
return syscall(43, fd, address, length)
|
return syscall(43, fd, address, length)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -21,6 +21,6 @@ listen(fd Int, backlog Int) -> Int {
|
|||||||
return syscall(50, fd, backlog)
|
return syscall(50, fd, backlog)
|
||||||
}
|
}
|
||||||
|
|
||||||
setsockopt(fd Int, level Int, optname Int, optval Pointer, optlen Int) -> Int {
|
setsockopt(fd Int, level Int, optname Int, optval *Any, optlen Int) -> Int {
|
||||||
return syscall(54, fd, level, optname, optval, optlen)
|
return syscall(54, fd, level, optname, optval, optlen)
|
||||||
}
|
}
|
@ -10,7 +10,7 @@ socket(family Int, type Int, protocol Int) -> Int {
|
|||||||
return syscall(0x2000061, family, type, protocol)
|
return syscall(0x2000061, family, type, protocol)
|
||||||
}
|
}
|
||||||
|
|
||||||
accept(fd Int, address Pointer, length Int) -> Int {
|
accept(fd Int, address *Any, length Int) -> Int {
|
||||||
return syscall(0x200001E, fd, address, length)
|
return syscall(0x200001E, fd, address, length)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
clone(flags Int, stack Pointer) -> Int {
|
clone(flags Int, stack *Any) -> Int {
|
||||||
return syscall(56, flags, stack)
|
return syscall(56, flags, stack)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -6,7 +6,7 @@ fork() -> Int {
|
|||||||
return syscall(57)
|
return syscall(57)
|
||||||
}
|
}
|
||||||
|
|
||||||
execve(path Pointer, argv Pointer, envp Pointer) -> Int {
|
execve(path *Any, argv *Any, envp *Any) -> Int {
|
||||||
return syscall(59, path, argv, envp)
|
return syscall(59, path, argv, envp)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -14,6 +14,6 @@ exit(status Int) {
|
|||||||
syscall(60, status)
|
syscall(60, status)
|
||||||
}
|
}
|
||||||
|
|
||||||
waitid(type Int, id Int, info Pointer, options Int) -> Int {
|
waitid(type Int, id Int, info *Any, options Int) -> Int {
|
||||||
return syscall(247, type, id, info, options)
|
return syscall(247, type, id, info, options)
|
||||||
}
|
}
|
@ -6,10 +6,10 @@ fork() -> Int {
|
|||||||
return syscall(0x2000002)
|
return syscall(0x2000002)
|
||||||
}
|
}
|
||||||
|
|
||||||
execve(path Pointer, argv Pointer, envp Pointer) -> Int {
|
execve(path *Any, argv *Any, envp *Any) -> Int {
|
||||||
return syscall(0x200003B, path, argv, envp)
|
return syscall(0x200003B, path, argv, envp)
|
||||||
}
|
}
|
||||||
|
|
||||||
waitid(type Int, id Int, info Pointer, options Int) -> Int {
|
waitid(type Int, id Int, info *Any, options Int) -> Int {
|
||||||
return syscall(0x20000AD, type, id, info, options)
|
return syscall(0x20000AD, type, id, info, options)
|
||||||
}
|
}
|
@ -1,6 +1,6 @@
|
|||||||
import sys
|
import sys
|
||||||
|
|
||||||
create(func Pointer) -> Int {
|
create(func *Any) -> Int {
|
||||||
size := 4096
|
size := 4096
|
||||||
stack := sys.mmap(0, size, 0x1|0x2, 0x02|0x20|0x100|0x20000)
|
stack := sys.mmap(0, size, 0x1|0x2, 0x02|0x20|0x100|0x20000)
|
||||||
rip := stack + size - 8
|
rip := stack + size - 8
|
||||||
|
@ -17,9 +17,10 @@ import (
|
|||||||
func (f *Function) CompileCall(root *expression.Expression) (*Function, error) {
|
func (f *Function) CompileCall(root *expression.Expression) (*Function, error) {
|
||||||
var (
|
var (
|
||||||
pkg = f.Package
|
pkg = f.Package
|
||||||
|
pkgNode *expression.Expression
|
||||||
|
name string
|
||||||
nameNode = root.Children[0]
|
nameNode = root.Children[0]
|
||||||
fn *Function
|
fn *Function
|
||||||
name string
|
|
||||||
exists bool
|
exists bool
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -53,8 +54,11 @@ func (f *Function) CompileCall(root *expression.Expression) (*Function, error) {
|
|||||||
return nil, f.CompileMemoryStore(root)
|
return nil, f.CompileMemoryStore(root)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
pkg = nameNode.Children[0].Token.Text(f.File.Bytes)
|
pkgNode = nameNode.Children[0]
|
||||||
name = nameNode.Children[1].Token.Text(f.File.Bytes)
|
nameNode = nameNode.Children[1]
|
||||||
|
|
||||||
|
pkg = pkgNode.Token.Text(f.File.Bytes)
|
||||||
|
name = nameNode.Token.Text(f.File.Bytes)
|
||||||
}
|
}
|
||||||
|
|
||||||
if pkg == "kernel32" || pkg == "user32" || pkg == "gdi32" || pkg == "comctl32" {
|
if pkg == "kernel32" || pkg == "user32" || pkg == "gdi32" || pkg == "comctl32" {
|
||||||
@ -74,13 +78,13 @@ func (f *Function) CompileCall(root *expression.Expression) (*Function, error) {
|
|||||||
return nil, nil
|
return nil, nil
|
||||||
} else if pkg != f.File.Package {
|
} else if pkg != f.File.Package {
|
||||||
if f.File.Imports == nil {
|
if f.File.Imports == nil {
|
||||||
return nil, errors.New(&errors.UnknownPackage{Name: pkg}, f.File, nameNode.Token.Position)
|
return nil, errors.New(&errors.UnknownPackage{Name: pkg}, f.File, pkgNode.Token.Position)
|
||||||
}
|
}
|
||||||
|
|
||||||
imp, exists := f.File.Imports[pkg]
|
imp, exists := f.File.Imports[pkg]
|
||||||
|
|
||||||
if !exists {
|
if !exists {
|
||||||
return nil, errors.New(&errors.UnknownPackage{Name: pkg}, f.File, nameNode.Token.Position)
|
return nil, errors.New(&errors.UnknownPackage{Name: pkg}, f.File, pkgNode.Token.Position)
|
||||||
}
|
}
|
||||||
|
|
||||||
imp.Used = true
|
imp.Used = true
|
||||||
@ -93,6 +97,11 @@ func (f *Function) CompileCall(root *expression.Expression) (*Function, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
parameters := root.Children[1:]
|
parameters := root.Children[1:]
|
||||||
|
|
||||||
|
if len(parameters) != len(fn.Input) {
|
||||||
|
return nil, errors.New(&errors.ParameterCountMismatch{Function: fn.Name, Count: len(parameters), ExpectedCount: len(fn.Input)}, f.File, nameNode.Token.End())
|
||||||
|
}
|
||||||
|
|
||||||
registers := f.CPU.Input[:len(parameters)]
|
registers := f.CPU.Input[:len(parameters)]
|
||||||
|
|
||||||
for i := len(parameters) - 1; i >= 0; i-- {
|
for i := len(parameters) - 1; i >= 0; i-- {
|
||||||
@ -107,9 +116,20 @@ func (f *Function) CompileCall(root *expression.Expression) (*Function, error) {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
encountered := ""
|
||||||
|
expected := ""
|
||||||
|
|
||||||
|
if typ != nil {
|
||||||
|
encountered = typ.Name()
|
||||||
|
}
|
||||||
|
|
||||||
|
if fn.Input[i].Type != nil {
|
||||||
|
expected = fn.Input[i].Type.Name()
|
||||||
|
}
|
||||||
|
|
||||||
return nil, errors.New(&errors.TypeMismatch{
|
return nil, errors.New(&errors.TypeMismatch{
|
||||||
Encountered: typ.Name(),
|
Encountered: encountered,
|
||||||
Expected: fn.Input[i].Type.Name(),
|
Expected: expected,
|
||||||
ParameterName: fn.Input[i].Name,
|
ParameterName: fn.Input[i].Name,
|
||||||
}, f.File, parameters[i].Token.Position)
|
}, f.File, parameters[i].Token.Position)
|
||||||
}
|
}
|
||||||
|
19
src/errors/ParameterCountMismatch.go
Normal file
19
src/errors/ParameterCountMismatch.go
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
package errors
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
// ParameterCountMismatch error is created when the number of parameters doesn't match the function prototype.
|
||||||
|
type ParameterCountMismatch struct {
|
||||||
|
Function string
|
||||||
|
Count int
|
||||||
|
ExpectedCount int
|
||||||
|
}
|
||||||
|
|
||||||
|
// Error generates the string representation.
|
||||||
|
func (err *ParameterCountMismatch) Error() string {
|
||||||
|
if err.Count > err.ExpectedCount {
|
||||||
|
return fmt.Sprintf("Too many parameters in '%s' function call", err.Function)
|
||||||
|
}
|
||||||
|
|
||||||
|
return fmt.Sprintf("Not enough parameters in '%s' function call", err.Function)
|
||||||
|
}
|
@ -9,6 +9,10 @@ type Array struct {
|
|||||||
|
|
||||||
// Name returns the type name.
|
// Name returns the type name.
|
||||||
func (a *Array) Name() string {
|
func (a *Array) Name() string {
|
||||||
|
if a.Of == Any {
|
||||||
|
return "[]Any"
|
||||||
|
}
|
||||||
|
|
||||||
return "[]" + a.Of.Name()
|
return "[]" + a.Of.Name()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,25 +10,27 @@ func ByName(name string, pkg string, structs map[string]*Struct) Type {
|
|||||||
to := strings.TrimPrefix(name, "*")
|
to := strings.TrimPrefix(name, "*")
|
||||||
typ := ByName(to, pkg, structs)
|
typ := ByName(to, pkg, structs)
|
||||||
|
|
||||||
if typ != nil {
|
if typ == Any {
|
||||||
return &Pointer{To: typ}
|
return AnyPointer
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return &Pointer{To: typ}
|
||||||
}
|
}
|
||||||
|
|
||||||
if strings.HasPrefix(name, "[]") {
|
if strings.HasPrefix(name, "[]") {
|
||||||
to := strings.TrimPrefix(name, "[]")
|
to := strings.TrimPrefix(name, "[]")
|
||||||
typ := ByName(to, pkg, structs)
|
typ := ByName(to, pkg, structs)
|
||||||
|
|
||||||
if typ != nil {
|
if typ == Any {
|
||||||
return &Array{Of: typ}
|
return AnyArray
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return &Array{Of: typ}
|
||||||
}
|
}
|
||||||
|
|
||||||
switch name {
|
switch name {
|
||||||
|
case "Any":
|
||||||
|
return Any
|
||||||
case "Int":
|
case "Int":
|
||||||
return Int
|
return Int
|
||||||
case "Int64":
|
case "Int64":
|
||||||
@ -45,8 +47,6 @@ func ByName(name string, pkg string, structs map[string]*Struct) Type {
|
|||||||
return Float64
|
return Float64
|
||||||
case "Float32":
|
case "Float32":
|
||||||
return Float32
|
return Float32
|
||||||
case "Pointer":
|
|
||||||
return AnyPointer
|
|
||||||
}
|
}
|
||||||
|
|
||||||
typ, exists := structs[pkg+"."+name]
|
typ, exists := structs[pkg+"."+name]
|
||||||
|
18
src/types/Common.go
Normal file
18
src/types/Common.go
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
package types
|
||||||
|
|
||||||
|
var (
|
||||||
|
Any = &Base{name: "Any", size: 0}
|
||||||
|
AnyArray = &Array{Of: Any}
|
||||||
|
AnyPointer = &Pointer{To: Any}
|
||||||
|
Int64 = &Base{name: "Int64", size: 8}
|
||||||
|
Int32 = &Base{name: "Int32", size: 4}
|
||||||
|
Int16 = &Base{name: "Int16", size: 2}
|
||||||
|
Int8 = &Base{name: "Int8", size: 1}
|
||||||
|
Float64 = &Base{name: "Float64", size: 8}
|
||||||
|
Float32 = &Base{name: "Float32", size: 4}
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
Int = Int64
|
||||||
|
Float = Float64
|
||||||
|
)
|
@ -1,7 +0,0 @@
|
|||||||
package types
|
|
||||||
|
|
||||||
var (
|
|
||||||
Float64 = &Base{name: "Float64", size: 8}
|
|
||||||
Float32 = &Base{name: "Float32", size: 4}
|
|
||||||
Float = Float64
|
|
||||||
)
|
|
@ -1,9 +0,0 @@
|
|||||||
package types
|
|
||||||
|
|
||||||
var (
|
|
||||||
Int64 = &Base{name: "Int64", size: 8}
|
|
||||||
Int32 = &Base{name: "Int32", size: 4}
|
|
||||||
Int16 = &Base{name: "Int16", size: 2}
|
|
||||||
Int8 = &Base{name: "Int8", size: 1}
|
|
||||||
Int = Int64
|
|
||||||
)
|
|
@ -2,30 +2,26 @@ package types
|
|||||||
|
|
||||||
// Is returns true if the encountered type `a` can be converted into the expected type `b`.
|
// Is returns true if the encountered type `a` can be converted into the expected type `b`.
|
||||||
func Is(a Type, b Type) bool {
|
func Is(a Type, b Type) bool {
|
||||||
if a == nil {
|
if a == b || b == Any || a == nil {
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
if a == b {
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
aPointer, aIsPointer := a.(*Pointer)
|
aPointer, aIsPointer := a.(*Pointer)
|
||||||
bPointer, bIsPointer := b.(*Pointer)
|
bPointer, bIsPointer := b.(*Pointer)
|
||||||
|
|
||||||
if aIsPointer && bIsPointer && (bPointer.To == nil || aPointer.To == bPointer.To) {
|
if aIsPointer && bIsPointer && (bPointer.To == Any || aPointer.To == bPointer.To) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
aArray, aIsArray := a.(*Array)
|
aArray, aIsArray := a.(*Array)
|
||||||
|
|
||||||
if aIsArray && bIsPointer && (bPointer.To == nil || aArray.Of == bPointer.To) {
|
if aIsArray && bIsPointer && (bPointer.To == Any || aArray.Of == bPointer.To) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
bArray, bIsArray := b.(*Array)
|
bArray, bIsArray := b.(*Array)
|
||||||
|
|
||||||
if aIsArray && bIsArray && aArray.Of == bArray.Of {
|
if aIsArray && bIsArray && (bArray.Of == Any || aArray.Of == bArray.Of) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,5 @@
|
|||||||
package types
|
package types
|
||||||
|
|
||||||
var AnyPointer = &Pointer{To: nil}
|
|
||||||
|
|
||||||
// Pointer is the address of an object.
|
// Pointer is the address of an object.
|
||||||
type Pointer struct {
|
type Pointer struct {
|
||||||
To Type
|
To Type
|
||||||
@ -10,7 +8,7 @@ type Pointer struct {
|
|||||||
// Name returns the type name.
|
// Name returns the type name.
|
||||||
func (p *Pointer) Name() string {
|
func (p *Pointer) Name() string {
|
||||||
if p.To == nil {
|
if p.To == nil {
|
||||||
return "Pointer"
|
return "*Any"
|
||||||
}
|
}
|
||||||
|
|
||||||
return "*" + p.To.Name()
|
return "*" + p.To.Name()
|
||||||
|
@ -9,7 +9,8 @@ import (
|
|||||||
|
|
||||||
func TestName(t *testing.T) {
|
func TestName(t *testing.T) {
|
||||||
assert.Equal(t, types.Int.Name(), "Int64")
|
assert.Equal(t, types.Int.Name(), "Int64")
|
||||||
assert.Equal(t, types.AnyPointer.Name(), "Pointer")
|
assert.Equal(t, types.AnyArray.Name(), "[]Any")
|
||||||
|
assert.Equal(t, types.AnyPointer.Name(), "*Any")
|
||||||
assert.Equal(t, (&types.Pointer{To: types.Int}).Name(), "*Int64")
|
assert.Equal(t, (&types.Pointer{To: types.Int}).Name(), "*Int64")
|
||||||
assert.Equal(t, (&types.Array{Of: types.Int}).Name(), "[]Int64")
|
assert.Equal(t, (&types.Array{Of: types.Int}).Name(), "[]Int64")
|
||||||
assert.Equal(t, types.String.Name(), "[]Int8")
|
assert.Equal(t, types.String.Name(), "[]Int8")
|
||||||
@ -21,6 +22,7 @@ func TestSize(t *testing.T) {
|
|||||||
assert.Equal(t, types.Int16.Size(), 2)
|
assert.Equal(t, types.Int16.Size(), 2)
|
||||||
assert.Equal(t, types.Int32.Size(), 4)
|
assert.Equal(t, types.Int32.Size(), 4)
|
||||||
assert.Equal(t, types.Int64.Size(), 8)
|
assert.Equal(t, types.Int64.Size(), 8)
|
||||||
|
assert.Equal(t, types.AnyArray.Size(), 8)
|
||||||
assert.Equal(t, types.AnyPointer.Size(), 8)
|
assert.Equal(t, types.AnyPointer.Size(), 8)
|
||||||
assert.Equal(t, types.String.Size(), 8)
|
assert.Equal(t, types.String.Size(), 8)
|
||||||
assert.Equal(t, (&types.Pointer{To: types.Int}).Size(), 8)
|
assert.Equal(t, (&types.Pointer{To: types.Int}).Size(), 8)
|
||||||
@ -39,9 +41,12 @@ func TestStruct(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestBasics(t *testing.T) {
|
func TestBasics(t *testing.T) {
|
||||||
|
assert.True(t, types.Is(types.Int, types.Any))
|
||||||
assert.True(t, types.Is(types.Int, types.Int))
|
assert.True(t, types.Is(types.Int, types.Int))
|
||||||
assert.True(t, types.Is(types.AnyPointer, types.AnyPointer))
|
assert.True(t, types.Is(types.AnyPointer, types.AnyPointer))
|
||||||
|
assert.True(t, types.Is(&types.Array{Of: types.Int}, types.AnyArray))
|
||||||
assert.False(t, types.Is(types.Int, types.Float))
|
assert.False(t, types.Is(types.Int, types.Float))
|
||||||
|
assert.False(t, types.Is(types.Any, types.Int))
|
||||||
assert.False(t, types.Is(&types.Pointer{To: types.Int}, &types.Pointer{To: types.Float}))
|
assert.False(t, types.Is(&types.Pointer{To: types.Int}, &types.Pointer{To: types.Float}))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -55,5 +60,9 @@ func TestSpecialCases(t *testing.T) {
|
|||||||
// A pointer pointing to a known type fulfills the requirement of a pointer to anything.
|
// A pointer pointing to a known type fulfills the requirement of a pointer to anything.
|
||||||
assert.True(t, types.Is(&types.Pointer{To: types.Int}, types.AnyPointer))
|
assert.True(t, types.Is(&types.Pointer{To: types.Int}, types.AnyPointer))
|
||||||
assert.True(t, types.Is(&types.Pointer{To: types.Float}, types.AnyPointer))
|
assert.True(t, types.Is(&types.Pointer{To: types.Float}, types.AnyPointer))
|
||||||
|
|
||||||
|
// Case #3:
|
||||||
|
// Arrays are also just pointers.
|
||||||
assert.True(t, types.Is(&types.Array{Of: types.Int}, types.AnyPointer))
|
assert.True(t, types.Is(&types.Array{Of: types.Int}, types.AnyPointer))
|
||||||
|
assert.True(t, types.Is(&types.Array{Of: types.Float}, types.AnyPointer))
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,6 @@ main() {
|
|||||||
writeToMemory(42)
|
writeToMemory(42)
|
||||||
}
|
}
|
||||||
|
|
||||||
writeToMemory(p Pointer) {
|
writeToMemory(p *Any) {
|
||||||
p[0] = 'A'
|
p[0] = 'A'
|
||||||
}
|
}
|
@ -46,7 +46,7 @@ var errs = []struct {
|
|||||||
{"MissingParameter3.q", errors.MissingParameter},
|
{"MissingParameter3.q", errors.MissingParameter},
|
||||||
{"MissingType.q", errors.MissingType},
|
{"MissingType.q", errors.MissingType},
|
||||||
{"ReturnCountMismatch.q", &errors.ReturnCountMismatch{Count: 1, ExpectedCount: 0}},
|
{"ReturnCountMismatch.q", &errors.ReturnCountMismatch{Count: 1, ExpectedCount: 0}},
|
||||||
{"TypeMismatch.q", &errors.TypeMismatch{Expected: "Pointer", Encountered: "Int64", ParameterName: "p"}},
|
{"TypeMismatch.q", &errors.TypeMismatch{Expected: "*Any", Encountered: "Int64", ParameterName: "p"}},
|
||||||
{"UnknownFunction.q", &errors.UnknownFunction{Name: "unknown"}},
|
{"UnknownFunction.q", &errors.UnknownFunction{Name: "unknown"}},
|
||||||
{"UnknownFunction2.q", &errors.UnknownFunction{Name: "f"}},
|
{"UnknownFunction2.q", &errors.UnknownFunction{Name: "f"}},
|
||||||
{"UnknownIdentifier.q", &errors.UnknownIdentifier{Name: "x"}},
|
{"UnknownIdentifier.q", &errors.UnknownIdentifier{Name: "x"}},
|
||||||
|
@ -2,6 +2,5 @@ import mem
|
|||||||
|
|
||||||
main() {
|
main() {
|
||||||
address := mem.alloc(1024)
|
address := mem.alloc(1024)
|
||||||
err := mem.free(address, 1024)
|
assert mem.free(address) == 0
|
||||||
assert err == 0
|
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user