Skip to content

Commit

Permalink
refactor: transform atom from uint64 to string
Browse files Browse the repository at this point in the history
  • Loading branch information
bdeneux committed Jul 19, 2024
1 parent e65dd08 commit 7e1b6c5
Show file tree
Hide file tree
Showing 6 changed files with 27 additions and 42 deletions.
24 changes: 5 additions & 19 deletions engine/atom.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,10 @@
package engine

import (
"crypto/sha256"
"encoding/binary"
"fmt"
"io"
"regexp"
"strings"
"unicode/utf8"
)

var (
Expand Down Expand Up @@ -199,26 +196,15 @@ var (
)

// Atom is a prolog atom.
type Atom struct {
value uint64
name string
}
type Atom string

// NewAtom interns the given string and returns an Atom.
func NewAtom(name string) Atom {
// A one-char atom is just a rune.
if r, n := utf8.DecodeLastRuneInString(name); r != utf8.RuneError && n == len(name) {
return Atom{uint64(r), name}
}

hashBytes := sha256.Sum256([]byte(name))
hashUint64 := binary.BigEndian.Uint64(hashBytes[:8])

return Atom{hashUint64, name}
return Atom(name)
}

func NewAtomRune(v rune) Atom {
return Atom{uint64(v), string(v)}
return Atom(v)
}

// WriteTerm outputs the Atom to an io.Writer.
Expand All @@ -227,7 +213,7 @@ func (a Atom) WriteTerm(w io.Writer, opts *WriteOptions, _ *Env) error {
openClose := (opts.left != (operator{}) || opts.right != (operator{})) && opts.getOps().defined(a)

if openClose {
if opts.left.name.value != 0 && opts.left.specifier.class() == operatorClassPrefix {
if opts.left.name != "" && opts.left.specifier.class() == operatorClassPrefix {
_, _ = ew.Write([]byte(" "))
}
_, _ = ew.Write([]byte("("))
Expand Down Expand Up @@ -279,7 +265,7 @@ func (a Atom) Compare(t Term, env *Env) int {
}

func (a Atom) String() string {
return a.name
return string(a)
}

// Apply returns a Compound which Functor is the Atom and args are the arguments. If the arguments are empty,
Expand Down
5 changes: 2 additions & 3 deletions engine/builtin.go
Original file line number Diff line number Diff line change
Expand Up @@ -1685,12 +1685,11 @@ func PutChar(vm *VM, streamOrAlias, char Term, k Cont, env *Env) *Promise {
case Variable:
return Error(InstantiationError(env))
case Atom:
if c.value > utf8.MaxRune {
r, n := utf8.DecodeLastRuneInString(c.String())
if r == utf8.RuneError || n != len(c.String()) {
return Error(typeError(validTypeCharacter, c, env))
}

r := rune(c.value)

switch _, err := s.WriteRune(r); {
case errors.Is(err, errWrongIOMode):
return Error(permissionError(operationOutput, permissionTypeStream, streamOrAlias, env))
Expand Down
4 changes: 2 additions & 2 deletions engine/compound.go
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,7 @@ func writeCompoundOpInfix(w io.Writer, c Compound, opts *WriteOptions, env *Env,
(opts.right != operator{} && r >= opts.right.priority)

if openClose {
if opts.left.name.value != 0 && opts.left.specifier.class() == operatorClassPrefix {
if opts.left.name != "" && opts.left.specifier.class() == operatorClassPrefix {
_, _ = fmt.Fprint(&ew, " ")
}
_, _ = fmt.Fprint(&ew, "(")
Expand Down Expand Up @@ -494,7 +494,7 @@ func pair(k, v Term) Term {
}

func tuple(args ...Term) Term {
return Atom{}.Apply(args...)
return Atom("").Apply(args...)
}

type charList string
Expand Down
28 changes: 14 additions & 14 deletions engine/parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -463,21 +463,21 @@ func (p *Parser) op(maxPriority Integer) (Atom, error) {
if p.current().kind == tokenCloseList {
p.backup()
}
return Atom{}, errNoOp
return "", errNoOp
case atomEmptyBlock:
p.backup()
if p.current().kind == tokenCloseCurly {
p.backup()
}
return Atom{}, errNoOp
return "", errNoOp
default:
return a, nil
}
}

t, err := p.next()
if err != nil {
return Atom{}, err
return "", err
}
switch t.kind {
case tokenComma:
Expand All @@ -489,7 +489,7 @@ func (p *Parser) op(maxPriority Integer) (Atom, error) {
}

p.backup()
return Atom{}, errExpectation
return "", errExpectation
}

func (p *Parser) term0(maxPriority Integer) (Term, error) {
Expand Down Expand Up @@ -571,7 +571,7 @@ func (p *Parser) term0Atom(maxPriority Integer) (Term, error) {
return nil, errExpectation
}

if p.placeholder.value != 0 && t == p.placeholder {
if p.placeholder != "" && t == p.placeholder {
if len(p.args) == 0 {
return nil, errPlaceholder
}
Expand Down Expand Up @@ -616,53 +616,53 @@ func (p *Parser) atom() (Atom, error) {

t, err := p.next()
if err != nil {
return Atom{}, err
return "", err
}
switch t.kind {
case tokenOpenList:
t, err := p.next()
if err != nil {
return Atom{}, err
return "", err
}
switch t.kind {
case tokenCloseList:
return atomEmptyList, nil
default:
p.backup()
p.backup()
return Atom{}, errExpectation
return "", errExpectation
}
case tokenOpenCurly:
t, err := p.next()
if err != nil {
return Atom{}, err
return "", err
}
switch t.kind {
case tokenCloseCurly:
return atomEmptyBlock, nil
default:
p.backup()
p.backup()
return Atom{}, errExpectation
return "", errExpectation
}
case tokenDoubleQuotedList:
switch p.doubleQuotes {
case doubleQuotesAtom:
return NewAtom(unDoubleQuote(t.val)), nil
default:
p.backup()
return Atom{}, errExpectation
return "", errExpectation
}
default:
p.backup()
return Atom{}, errExpectation
return "", errExpectation
}
}

func (p *Parser) name() (Atom, error) {
t, err := p.next()
if err != nil {
return Atom{}, err
return "", err
}
switch t.kind {
case tokenLetterDigit, tokenGraphic, tokenSemicolon, tokenCut:
Expand All @@ -671,7 +671,7 @@ func (p *Parser) name() (Atom, error) {
return NewAtom(unquote(t.val)), nil
default:
p.backup()
return Atom{}, errExpectation
return "", errExpectation
}
}

Expand Down
4 changes: 2 additions & 2 deletions engine/stream.go
Original file line number Diff line number Diff line change
Expand Up @@ -359,7 +359,7 @@ func (s *Stream) properties() []Term {
ps = append(ps, atomOutput)
}

if s.alias.value != 0 {
if s.alias != "" {
ps = append(ps, atomAlias.Apply(s.alias))
}

Expand Down Expand Up @@ -510,7 +510,7 @@ type streams struct {
}

func (ss *streams) add(s *Stream) {
if s.alias.value != 0 {
if s.alias != "" {
if ss.aliases == nil {
ss.aliases = map[Atom]*Stream{}
}
Expand Down
4 changes: 2 additions & 2 deletions engine/term_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,13 +48,13 @@ func TestCompareAtomic(t *testing.T) {
{a: &y{}, t: NewVariable(), o: 1},
{a: &y{}, t: NewFloatFromInt64(0), o: 1},
{a: &y{}, t: Integer(0), o: 1},
{a: &y{}, t: Atom{}, o: 1},
{a: &y{}, t: Atom(""), o: 1},
{a: &y{}, t: &x{}, o: 1},
{a: &y{val: 1}, t: &y{val: 0}, cmp: cmp, o: 1},
{a: &y{val: 0}, t: &y{val: 0}, cmp: cmp, o: 0},
{a: &y{val: 0}, t: &y{val: 1}, cmp: cmp, o: -1},
{a: &y{}, t: &z{}, o: -1},
{a: &y{}, t: Atom{}.Apply(Integer(0)), o: -1},
{a: &y{}, t: Atom("").Apply(Integer(0)), o: -1},
}

for _, tt := range tests {
Expand Down

0 comments on commit 7e1b6c5

Please sign in to comment.