Implemented numbers with different bases
This commit is contained in:
parent
f1d4e65c1b
commit
d5953649d9
@ -112,10 +112,10 @@ This is what generates expressions from tokens.
|
|||||||
- [x] Variable lifetimes
|
- [x] Variable lifetimes
|
||||||
- [x] Branches
|
- [x] Branches
|
||||||
- [x] Loops
|
- [x] Loops
|
||||||
|
- [x] Hexadecimal, octal and binary literals
|
||||||
- [ ] Data structures
|
- [ ] Data structures
|
||||||
- [ ] Type system
|
- [ ] Type system
|
||||||
- [ ] Type operator: `|` (`User | Error`)
|
- [ ] Type operator: `|` (`User | Error`)
|
||||||
- [ ] Hexadecimal, octal and binary literals
|
|
||||||
- [ ] Error handling
|
- [ ] Error handling
|
||||||
- [ ] Multiple return values
|
- [ ] Multiple return values
|
||||||
- [ ] Threading library
|
- [ ] Threading library
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import sys
|
import sys
|
||||||
|
|
||||||
alloc(length) {
|
alloc(length) {
|
||||||
return sys.mmap(0, length, 3, 290)
|
return sys.mmap(0, length, 0x1|0x2, 0x02|0x20|0x100)
|
||||||
}
|
}
|
||||||
|
|
||||||
free(address, length) {
|
free(address, length) {
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
package core
|
package core
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"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/cpu"
|
"git.akyoto.dev/cli/q/src/build/cpu"
|
||||||
@ -28,7 +26,6 @@ func (f *Function) ExpressionToRegister(node *expression.Expression, register cp
|
|||||||
|
|
||||||
if len(node.Children) == 1 {
|
if len(node.Children) == 1 {
|
||||||
if !node.Token.IsUnaryOperator() {
|
if !node.Token.IsUnaryOperator() {
|
||||||
fmt.Println(node.String(f.File.Bytes), node.Token.Kind)
|
|
||||||
return errors.New(errors.MissingOperand, f.File, node.Token.End())
|
return errors.New(errors.MissingOperand, f.File, node.Token.End())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,6 +2,7 @@ package core
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"strings"
|
||||||
"unicode/utf8"
|
"unicode/utf8"
|
||||||
|
|
||||||
"git.akyoto.dev/cli/q/src/build/errors"
|
"git.akyoto.dev/cli/q/src/build/errors"
|
||||||
@ -12,7 +13,24 @@ import (
|
|||||||
func (f *Function) Number(t token.Token) (int, byte, error) {
|
func (f *Function) Number(t token.Token) (int, byte, error) {
|
||||||
switch t.Kind {
|
switch t.Kind {
|
||||||
case token.Number:
|
case token.Number:
|
||||||
number, err := strconv.Atoi(t.Text(f.File.Bytes))
|
digits := t.Text(f.File.Bytes)
|
||||||
|
|
||||||
|
if strings.HasPrefix(digits, "0x") {
|
||||||
|
number, err := strconv.ParseInt(digits[2:], 16, 64)
|
||||||
|
return int(number), 8, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if strings.HasPrefix(digits, "0o") {
|
||||||
|
number, err := strconv.ParseInt(digits[2:], 8, 64)
|
||||||
|
return int(number), 8, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if strings.HasPrefix(digits, "0b") {
|
||||||
|
number, err := strconv.ParseInt(digits[2:], 2, 64)
|
||||||
|
return int(number), 8, err
|
||||||
|
}
|
||||||
|
|
||||||
|
number, err := strconv.Atoi(digits)
|
||||||
return number, 8, err
|
return number, 8, err
|
||||||
|
|
||||||
case token.Rune:
|
case token.Rune:
|
||||||
|
@ -94,6 +94,38 @@ func Tokenize(buffer []byte) List {
|
|||||||
tokens = append(tokens, Token{Kind: kind, Position: start, Length: Length(end - start)})
|
tokens = append(tokens, Token{Kind: kind, Position: start, Length: Length(end - start)})
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
case '0':
|
||||||
|
position := i
|
||||||
|
i++
|
||||||
|
|
||||||
|
if i >= Position(len(buffer)) {
|
||||||
|
tokens = append(tokens, Token{Kind: Number, Position: position, Length: 1})
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
filter := isDigit
|
||||||
|
|
||||||
|
switch buffer[i] {
|
||||||
|
case 'x':
|
||||||
|
i++
|
||||||
|
filter = isHexDigit
|
||||||
|
|
||||||
|
case 'b':
|
||||||
|
i++
|
||||||
|
filter = isBinaryDigit
|
||||||
|
|
||||||
|
case 'o':
|
||||||
|
i++
|
||||||
|
filter = isOctalDigit
|
||||||
|
}
|
||||||
|
|
||||||
|
for i < Position(len(buffer)) && filter(buffer[i]) {
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
|
||||||
|
tokens = append(tokens, Token{Kind: Number, Position: position, Length: Length(i - position)})
|
||||||
|
continue
|
||||||
|
|
||||||
default:
|
default:
|
||||||
if isIdentifierStart(buffer[i]) {
|
if isIdentifierStart(buffer[i]) {
|
||||||
position := i
|
position := i
|
||||||
@ -123,11 +155,11 @@ func Tokenize(buffer []byte) List {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if isNumber(buffer[i]) {
|
if isDigit(buffer[i]) {
|
||||||
position := i
|
position := i
|
||||||
i++
|
i++
|
||||||
|
|
||||||
for i < Position(len(buffer)) && isNumber(buffer[i]) {
|
for i < Position(len(buffer)) && isDigit(buffer[i]) {
|
||||||
i++
|
i++
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -235,7 +267,7 @@ func Tokenize(buffer []byte) List {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func isIdentifier(c byte) bool {
|
func isIdentifier(c byte) bool {
|
||||||
return isLetter(c) || isNumber(c) || c == '_'
|
return isLetter(c) || isDigit(c) || c == '_'
|
||||||
}
|
}
|
||||||
|
|
||||||
func isIdentifierStart(c byte) bool {
|
func isIdentifierStart(c byte) bool {
|
||||||
@ -246,8 +278,20 @@ func isLetter(c byte) bool {
|
|||||||
return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')
|
return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')
|
||||||
}
|
}
|
||||||
|
|
||||||
func isNumber(c byte) bool {
|
func isDigit(c byte) bool {
|
||||||
return (c >= '0' && c <= '9')
|
return c >= '0' && c <= '9'
|
||||||
|
}
|
||||||
|
|
||||||
|
func isHexDigit(c byte) bool {
|
||||||
|
return (c >= '0' && c <= '9') || (c >= 'A' && c <= 'F')
|
||||||
|
}
|
||||||
|
|
||||||
|
func isBinaryDigit(c byte) bool {
|
||||||
|
return c == '0' || c == '1'
|
||||||
|
}
|
||||||
|
|
||||||
|
func isOctalDigit(c byte) bool {
|
||||||
|
return c >= '0' && c <= '7'
|
||||||
}
|
}
|
||||||
|
|
||||||
func isOperator(c byte) bool {
|
func isOperator(c byte) bool {
|
||||||
|
@ -179,6 +179,71 @@ func TestNegateNumber(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestBinaryNumber(t *testing.T) {
|
||||||
|
tokens := token.Tokenize([]byte(`0b1010`))
|
||||||
|
|
||||||
|
expected := []token.Kind{
|
||||||
|
token.Number,
|
||||||
|
token.EOF,
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, kind := range expected {
|
||||||
|
assert.Equal(t, tokens[i].Kind, kind)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestOctalNumber(t *testing.T) {
|
||||||
|
tokens := token.Tokenize([]byte(`0o755`))
|
||||||
|
|
||||||
|
expected := []token.Kind{
|
||||||
|
token.Number,
|
||||||
|
token.EOF,
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, kind := range expected {
|
||||||
|
assert.Equal(t, tokens[i].Kind, kind)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestHexadecimalNumber(t *testing.T) {
|
||||||
|
tokens := token.Tokenize([]byte(`0xCAFE`))
|
||||||
|
|
||||||
|
expected := []token.Kind{
|
||||||
|
token.Number,
|
||||||
|
token.EOF,
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, kind := range expected {
|
||||||
|
assert.Equal(t, tokens[i].Kind, kind)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestStandaloneZero(t *testing.T) {
|
||||||
|
tokens := token.Tokenize([]byte(`0`))
|
||||||
|
|
||||||
|
expected := []token.Kind{
|
||||||
|
token.Number,
|
||||||
|
token.EOF,
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, kind := range expected {
|
||||||
|
assert.Equal(t, tokens[i].Kind, kind)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestLeadingZero(t *testing.T) {
|
||||||
|
tokens := token.Tokenize([]byte(`0123`))
|
||||||
|
|
||||||
|
expected := []token.Kind{
|
||||||
|
token.Number,
|
||||||
|
token.EOF,
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, kind := range expected {
|
||||||
|
assert.Equal(t, tokens[i].Kind, kind)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestOperatorAssign(t *testing.T) {
|
func TestOperatorAssign(t *testing.T) {
|
||||||
tokens := token.Tokenize([]byte(`a += b -= c *= d /= e &= f |= g ^= h <<= i >>= j`))
|
tokens := token.Tokenize([]byte(`a += b -= c *= d /= e &= f |= g ^= h <<= i >>= j`))
|
||||||
|
|
||||||
|
10
tests/programs/binary.q
Normal file
10
tests/programs/binary.q
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
main() {
|
||||||
|
assert 0b0 == 0
|
||||||
|
assert 0b1 == 1
|
||||||
|
assert 0b10 == 2
|
||||||
|
assert 0b11 == 3
|
||||||
|
assert 0b100 == 4
|
||||||
|
assert 0b101 == 5
|
||||||
|
assert 0b110 == 6
|
||||||
|
assert 0b111 == 7
|
||||||
|
}
|
8
tests/programs/hexadecimal.q
Normal file
8
tests/programs/hexadecimal.q
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
main() {
|
||||||
|
assert 0x0 == 0
|
||||||
|
assert 0x1 == 1
|
||||||
|
assert 0xA == 10
|
||||||
|
assert 0x10 == 16
|
||||||
|
assert 0xFF == 255
|
||||||
|
assert 0x1000 == 4096
|
||||||
|
}
|
8
tests/programs/octal.q
Normal file
8
tests/programs/octal.q
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
main() {
|
||||||
|
assert 0o0 == 0
|
||||||
|
assert 0o1 == 1
|
||||||
|
assert 0o7 == 7
|
||||||
|
assert 0o10 == 8
|
||||||
|
assert 0o100 == 64
|
||||||
|
assert 0o755 == 493
|
||||||
|
}
|
@ -22,6 +22,9 @@ var programs = []struct {
|
|||||||
{"reuse", "", "", 0},
|
{"reuse", "", "", 0},
|
||||||
{"reassign", "", "", 0},
|
{"reassign", "", "", 0},
|
||||||
{"return", "", "", 0},
|
{"return", "", "", 0},
|
||||||
|
{"binary", "", "", 0},
|
||||||
|
{"octal", "", "", 0},
|
||||||
|
{"hexadecimal", "", "", 0},
|
||||||
{"math", "", "", 0},
|
{"math", "", "", 0},
|
||||||
{"precedence", "", "", 0},
|
{"precedence", "", "", 0},
|
||||||
{"bitwise-and", "", "", 0},
|
{"bitwise-and", "", "", 0},
|
||||||
@ -30,7 +33,7 @@ var programs = []struct {
|
|||||||
{"shift", "", "", 0},
|
{"shift", "", "", 0},
|
||||||
{"modulo", "", "", 0},
|
{"modulo", "", "", 0},
|
||||||
{"modulo-assign", "", "", 0},
|
{"modulo-assign", "", "", 0},
|
||||||
{"division-split", "", "", 0},
|
{"div-split", "", "", 0},
|
||||||
{"negative", "", "", 0},
|
{"negative", "", "", 0},
|
||||||
{"negation", "", "", 0},
|
{"negation", "", "", 0},
|
||||||
{"square-sum", "", "", 0},
|
{"square-sum", "", "", 0},
|
||||||
|
Loading…
Reference in New Issue
Block a user