aboutsummaryrefslogtreecommitdiffstats
path: root/pkg
diff options
context:
space:
mode:
Diffstat (limited to 'pkg')
-rw-r--r--pkg/ast/ast.go15
-rw-r--r--pkg/ast/clone.go6
-rw-r--r--pkg/ast/format.go34
-rw-r--r--pkg/ast/parser.go17
-rw-r--r--pkg/ast/scanner.go29
-rw-r--r--pkg/ast/testdata/all.txt1
-rw-r--r--pkg/compiler/testdata/all.txt6
-rw-r--r--pkg/compiler/testdata/errors.txt1
-rw-r--r--pkg/compiler/testdata/errors2.txt5
-rw-r--r--pkg/compiler/types.go44
10 files changed, 96 insertions, 62 deletions
diff --git a/pkg/ast/ast.go b/pkg/ast/ast.go
index 610d22f30..1e1e97221 100644
--- a/pkg/ast/ast.go
+++ b/pkg/ast/ast.go
@@ -169,19 +169,20 @@ func (n *String) Info() (Pos, string, string) {
return n.Pos, tok2str[tokString], ""
}
-type intFmt int
+type IntFmt int
const (
- intFmtDec intFmt = iota
- intFmtHex
- intFmtChar
+ IntFmtDec IntFmt = iota
+ IntFmtNeg
+ IntFmtHex
+ IntFmtChar
)
type Int struct {
Pos Pos
// Only one of Value, Ident, CExpr is filled.
Value uint64
- valueFmt intFmt
+ ValueFmt IntFmt
Ident string
CExpr string
}
@@ -194,7 +195,7 @@ type Type struct {
Pos Pos
// Only one of Value, Ident, String is filled.
Value uint64
- valueFmt intFmt
+ ValueFmt IntFmt
Ident string
String string
HasString bool
@@ -202,7 +203,7 @@ type Type struct {
HasColon bool
Pos2 Pos
Value2 uint64
- value2Fmt intFmt
+ Value2Fmt IntFmt
Ident2 string
Args []*Type
}
diff --git a/pkg/ast/clone.go b/pkg/ast/clone.go
index 9ccc3ea76..072425115 100644
--- a/pkg/ast/clone.go
+++ b/pkg/ast/clone.go
@@ -165,7 +165,7 @@ func (n *Int) Clone() Node {
return &Int{
Pos: n.Pos,
Value: n.Value,
- valueFmt: n.valueFmt,
+ ValueFmt: n.ValueFmt,
Ident: n.Ident,
CExpr: n.CExpr,
}
@@ -179,14 +179,14 @@ func (n *Type) Clone() Node {
return &Type{
Pos: n.Pos,
Value: n.Value,
- valueFmt: n.valueFmt,
+ ValueFmt: n.ValueFmt,
Ident: n.Ident,
String: n.String,
HasString: n.HasString,
HasColon: n.HasColon,
Pos2: n.Pos2,
Value2: n.Value2,
- value2Fmt: n.value2Fmt,
+ Value2Fmt: n.Value2Fmt,
Ident2: n.Ident2,
Args: args,
}
diff --git a/pkg/ast/format.go b/pkg/ast/format.go
index 5022d5da1..13cd26e2c 100644
--- a/pkg/ast/format.go
+++ b/pkg/ast/format.go
@@ -35,6 +35,21 @@ func SerializeNode(n Node) string {
return buf.String()
}
+func FormatInt(v uint64, format IntFmt) string {
+ switch format {
+ case IntFmtDec:
+ return fmt.Sprint(v)
+ case IntFmtNeg:
+ return fmt.Sprint(int64(v))
+ case IntFmtHex:
+ return fmt.Sprintf("0x%x", v)
+ case IntFmtChar:
+ return fmt.Sprintf("'%c'", v)
+ default:
+ panic(fmt.Sprintf("unknown int format %v", format))
+ }
+}
+
type serializer interface {
serialize(w io.Writer)
}
@@ -159,14 +174,14 @@ func fmtType(t *Type) string {
case t.HasString:
v = fmt.Sprintf("\"%v\"", t.String)
default:
- v = fmtIntValue(t.Value, t.valueFmt)
+ v = FormatInt(t.Value, t.ValueFmt)
}
if t.HasColon {
switch {
case t.Ident2 != "":
v += fmt.Sprintf(":%v", t.Ident2)
default:
- v += fmt.Sprintf(":%v", fmtIntValue(t.Value2, t.value2Fmt))
+ v += fmt.Sprintf(":%v", FormatInt(t.Value2, t.Value2Fmt))
}
}
v += fmtTypeList(t.Args)
@@ -206,20 +221,7 @@ func fmtInt(i *Int) string {
case i.CExpr != "":
return fmt.Sprintf("%v", i.CExpr)
default:
- return fmtIntValue(i.Value, i.valueFmt)
- }
-}
-
-func fmtIntValue(v uint64, format intFmt) string {
- switch format {
- case intFmtDec:
- return fmt.Sprint(v)
- case intFmtHex:
- return fmt.Sprintf("0x%x", v)
- case intFmtChar:
- return fmt.Sprintf("'%c'", v)
- default:
- panic(fmt.Sprintf("unknown int format %v", format))
+ return FormatInt(i.Value, i.ValueFmt)
}
}
diff --git a/pkg/ast/parser.go b/pkg/ast/parser.go
index e4c5d8742..d43011796 100644
--- a/pkg/ast/parser.go
+++ b/pkg/ast/parser.go
@@ -413,7 +413,7 @@ func (p *parser) parseType() *Type {
switch p.tok {
case tokInt:
allowColon = true
- arg.Value, arg.valueFmt = p.parseIntValue()
+ arg.Value, arg.ValueFmt = p.parseIntValue()
case tokIdent:
allowColon = true
arg.Ident = p.lit
@@ -429,7 +429,7 @@ func (p *parser) parseType() *Type {
arg.Pos2 = p.pos
switch p.tok {
case tokInt:
- arg.Value2, arg.value2Fmt = p.parseIntValue()
+ arg.Value2, arg.Value2Fmt = p.parseIntValue()
case tokIdent:
arg.Ident2 = p.lit
default:
@@ -479,7 +479,7 @@ func (p *parser) parseInt() *Int {
}
switch p.tok {
case tokInt:
- i.Value, i.valueFmt = p.parseIntValue()
+ i.Value, i.ValueFmt = p.parseIntValue()
case tokIdent:
i.Ident = p.lit
default:
@@ -489,16 +489,19 @@ func (p *parser) parseInt() *Int {
return i
}
-func (p *parser) parseIntValue() (uint64, intFmt) {
+func (p *parser) parseIntValue() (uint64, IntFmt) {
if p.lit[0] == '\'' {
- return uint64(p.lit[1]), intFmtChar
+ return uint64(p.lit[1]), IntFmtChar
}
if v, err := strconv.ParseUint(p.lit, 10, 64); err == nil {
- return v, intFmtDec
+ return v, IntFmtDec
+ }
+ if v, err := strconv.ParseInt(p.lit, 10, 64); err == nil {
+ return uint64(v), IntFmtNeg
}
if len(p.lit) > 2 && p.lit[0] == '0' && p.lit[1] == 'x' {
if v, err := strconv.ParseUint(p.lit[2:], 16, 64); err == nil {
- return v, intFmtHex
+ return v, IntFmtHex
}
}
panic(fmt.Sprintf("scanner returned bad integer %q", p.lit))
diff --git a/pkg/ast/scanner.go b/pkg/ast/scanner.go
index 67e7f50bd..af9ac562f 100644
--- a/pkg/ast/scanner.go
+++ b/pkg/ast/scanner.go
@@ -150,7 +150,7 @@ func (s *scanner) Scan() (tok token, lit string, pos Pos) {
case s.ch == '"' || s.ch == '<':
tok = tokString
lit = s.scanStr(pos)
- case s.ch >= '0' && s.ch <= '9':
+ case s.ch >= '0' && s.ch <= '9' || s.ch == '-':
tok = tokInt
lit = s.scanInt(pos)
case s.ch == '\'':
@@ -211,25 +211,26 @@ func (s *scanner) scanStr(pos Pos) string {
func (s *scanner) scanInt(pos Pos) string {
for s.ch >= '0' && s.ch <= '9' ||
s.ch >= 'a' && s.ch <= 'f' ||
- s.ch >= 'A' && s.ch <= 'F' || s.ch == 'x' {
+ s.ch >= 'A' && s.ch <= 'F' ||
+ s.ch == 'x' || s.ch == '-' {
s.next()
}
lit := string(s.data[pos.Off:s.off])
- bad := false
- if _, err := strconv.ParseUint(lit, 10, 64); err != nil {
- if len(lit) > 2 && lit[0] == '0' && lit[1] == 'x' {
- if _, err := strconv.ParseUint(lit[2:], 16, 64); err != nil {
- bad = true
- }
- } else {
- bad = true
+ if _, err := strconv.ParseUint(lit, 10, 64); err == nil {
+ return lit
+ }
+ if len(lit) > 1 && lit[0] == '-' {
+ if _, err := strconv.ParseInt(lit, 10, 64); err == nil {
+ return lit
}
}
- if bad {
- s.Error(pos, fmt.Sprintf("bad integer %q", lit))
- lit = "0"
+ if len(lit) > 2 && lit[0] == '0' && lit[1] == 'x' {
+ if _, err := strconv.ParseUint(lit[2:], 16, 64); err == nil {
+ return lit
+ }
}
- return lit
+ s.Error(pos, fmt.Sprintf("bad integer %q", lit))
+ return "0"
}
func (s *scanner) scanChar(pos Pos) string {
diff --git a/pkg/ast/testdata/all.txt b/pkg/ast/testdata/all.txt
index 6c818eca6..6e4e72d2c 100644
--- a/pkg/ast/testdata/all.txt
+++ b/pkg/ast/testdata/all.txt
@@ -12,6 +12,7 @@ int_flags = 0, "foo" ### unexpected string, expecting int, identifier
int_flags2 = ' ### char literal is not terminated
int_flags3 = 'a ### char literal is not terminated
int_flags3 = 'a, 1 ### char literal is not terminated
+int_flags4 = 1, -2- ### bad integer "-2-"
str_flags0 = "foo", "bar"
str_flags1 = "non terminated ### string literal is not terminated
diff --git a/pkg/compiler/testdata/all.txt b/pkg/compiler/testdata/all.txt
index 573fb6412..6fff34284 100644
--- a/pkg/compiler/testdata/all.txt
+++ b/pkg/compiler/testdata/all.txt
@@ -7,7 +7,9 @@ foo$2(a ptr[out, array[int32]])
foo$3(a union_arg)
foo$4() r0
foo$5(a int8['a':'z'])
-foo$6(a ptr[in, strings])
+foo$6(a int8[-20:-10])
+foo$7(a int8[-20:20])
+foo$8(a ptr[in, strings])
resource r0[intptr]
@@ -38,7 +40,7 @@ strings {
string_flags1 = "foo", "barbaz"
string_flags2 = ""
-int_flags = 0, 1
+int_flags = 0, 1, 0xabc, 'x', -11
_ = 1, 2
_ = C1, C2
diff --git a/pkg/compiler/testdata/errors.txt b/pkg/compiler/testdata/errors.txt
index cbfebbfd7..3c2cb57ae 100644
--- a/pkg/compiler/testdata/errors.txt
+++ b/pkg/compiler/testdata/errors.txt
@@ -329,4 +329,5 @@ foo$fmt4(a ptr[in, fmt[dec, int8:3]]) ### unexpected ':', only struct fields ca
struct$fmt0 {
f0 fmt[dec, int8:3] ### unexpected ':', only struct fields can be bitfields
+ f1 int32:-1 ### bitfield of size 18446744073709551615 is too large for base type of size 32
}
diff --git a/pkg/compiler/testdata/errors2.txt b/pkg/compiler/testdata/errors2.txt
index 1b1adefa5..77db29197 100644
--- a/pkg/compiler/testdata/errors2.txt
+++ b/pkg/compiler/testdata/errors2.txt
@@ -217,6 +217,11 @@ foo$507(a ptr[in, array[int32, 0:0]]) ### arrays of size 0 are not supported
foo$508(a ptr[in, string["foo", 3]]) ### string value "foo\x00" exceeds buffer length 3
foo$509(a int8['b':'a']) ### bad int range [98:97]
foo$510(a type500)
+foo$511(a int32[-10:-20]) ### bad int range [18446744073709551606:18446744073709551596]
+foo$512(a ptr[in, array[int8, -2:-1]]) ### bad size range [18446744073709551614:18446744073709551615]
+foo$513(a ptr[in, array[int8, -2:2]]) ### bad size range [18446744073709551614:2]
+foo$514(a vma[-2:2]) ### bad size range [18446744073709551614:2]
+foo$515(a ptr[in, proc[1, -10, int64]]) ### values starting from 1 with step 18446744073709551606 overflow base type for 32 procs
type type500 proc[C1, 8, int8] ### values starting from 1 with step 8 overflow base type for 32 procs
type type501 int8 ### unused type type501
diff --git a/pkg/compiler/types.go b/pkg/compiler/types.go
index 156b1505a..293496a9c 100644
--- a/pkg/compiler/types.go
+++ b/pkg/compiler/types.go
@@ -68,7 +68,7 @@ var typeInt = &typeDesc{
AllowColon: true,
ResourceBase: true,
OptArgs: 1,
- Args: []namedArg{{Name: "range", Type: typeArgRange}},
+ Args: []namedArg{{Name: "range", Type: typeArgIntRange}},
Check: func(comp *compiler, t *ast.Type, args []*ast.Type, base prog.IntTypeCommon) {
typeArgBase.Type.Check(comp, t)
},
@@ -128,7 +128,7 @@ var typeArray = &typeDesc{
CanBeTypedef: true,
CantBeOpt: true,
OptArgs: 1,
- Args: []namedArg{{Name: "type", Type: typeArgType}, {Name: "size", Type: typeArgRange}},
+ Args: []namedArg{{Name: "type", Type: typeArgType}, {Name: "size", Type: typeArgSizeRange}},
CheckConsts: func(comp *compiler, t *ast.Type, args []*ast.Type, base prog.IntTypeCommon) {
if len(args) > 1 && args[1].Value == 0 && args[1].Value2 == 0 {
comp.error(args[1].Pos, "arrays of size 0 are not supported")
@@ -290,7 +290,7 @@ var typeVMA = &typeDesc{
Names: []string{"vma"},
CanBeArgRet: canBeArg,
OptArgs: 1,
- Args: []namedArg{{Name: "size range", Type: typeArgRange}},
+ Args: []namedArg{{Name: "size range", Type: typeArgSizeRange}},
Gen: func(comp *compiler, t *ast.Type, args []*ast.Type, base prog.IntTypeCommon) prog.Type {
begin, end := uint64(0), uint64(0)
if len(args) > 0 {
@@ -367,14 +367,16 @@ var typeProc = &typeDesc{
return
}
size := base.TypeSize * 8
- if size != 64 {
- const maxPids = 32 // executor knows about this constant (MAX_PIDS)
- if start >= 1<<size {
- comp.error(args[0].Pos, "values starting from %v overflow base type", start)
- } else if start+maxPids*perProc > 1<<size {
- comp.error(args[0].Pos, "values starting from %v with step %v overflow base type for %v procs",
- start, perProc, maxPids)
- }
+ max := uint64(1) << size
+ if size == 64 {
+ max = ^uint64(0)
+ }
+ const maxPids = 32 // executor knows about this constant (MAX_PIDS)
+ if start >= max {
+ comp.error(args[0].Pos, "values starting from %v overflow base type", start)
+ } else if perProc > (max-start)/maxPids {
+ comp.error(args[0].Pos, "values starting from %v with step %v overflow base type for %v procs",
+ start, perProc, maxPids)
}
},
Gen: func(comp *compiler, t *ast.Type, args []*ast.Type, base prog.IntTypeCommon) prog.Type {
@@ -763,19 +765,35 @@ var typeArgInt = &typeArg{
Kind: kindInt,
}
-var typeArgRange = &typeArg{
+var typeArgIntRange = &typeArg{
Kind: kindInt,
AllowColon: true,
CheckConsts: func(comp *compiler, t *ast.Type) {
if !t.HasColon {
t.Value2 = t.Value
+ t.Value2Fmt = t.ValueFmt
}
- if t.Value > t.Value2 {
+ if t.Value2-t.Value > 1<<64-1<<32 {
comp.error(t.Pos, "bad int range [%v:%v]", t.Value, t.Value2)
}
},
}
+// Size of array and vma's.
+var typeArgSizeRange = &typeArg{
+ Kind: kindInt,
+ AllowColon: true,
+ CheckConsts: func(comp *compiler, t *ast.Type) {
+ if !t.HasColon {
+ t.Value2 = t.Value
+ }
+ const maxVal = 1e6
+ if t.Value > t.Value2 || t.Value > maxVal || t.Value2 > maxVal {
+ comp.error(t.Pos, "bad size range [%v:%v]", t.Value, t.Value2)
+ }
+ },
+}
+
// Base type of const/len/etc. Same as typeInt, but can't have range.
var typeArgBase = namedArg{
Name: "base type",