From 5089fe689f17a3489b6be76588b8fc7f93d70e55 Mon Sep 17 00:00:00 2001 From: Charlie Stanton Date: Wed, 19 Apr 2023 14:13:32 +0100 Subject: Adds a dummy method to atom so the compiler checks that only valid atoms are allowed --- subex/parse.go | 12 ++++++------ walk/walk.go | 26 +++++++++++++++++++++----- 2 files changed, 27 insertions(+), 11 deletions(-) diff --git a/subex/parse.go b/subex/parse.go index 8b3a553..d6ef995 100644 --- a/subex/parse.go +++ b/subex/parse.go @@ -109,7 +109,7 @@ func parseReplacement(l *RuneReader) (output []OutputContent) { case '@', '~', '#': output = append(output, OutputAtomLiteral{atom: parseTerminatorAtomLiteral(r, l)}) default: - output = append(output, OutputAtomLiteral{atom: r}) + output = append(output, OutputAtomLiteral{atom: walk.StringAtom(r)}) } } return output @@ -143,10 +143,10 @@ func parseRangeSubex(l *RuneReader) map[walk.Atom]walk.Atom { fromsEnd = fromsStart } for i := fromsStart; i <= fromsEnd; i += 1 { - froms = append(froms, i) + froms = append(froms, walk.StringAtom(i)) } } else { - froms = append(froms, fromsStart) + froms = append(froms, walk.StringAtom(fromsStart)) } } if len(froms) == 0 { @@ -173,10 +173,10 @@ func parseRangeSubex(l *RuneReader) map[walk.Atom]walk.Atom { tosEnd = tosStart } for i := tosStart; i <= tosEnd; i += 1 { - tos = append(tos, i) + tos = append(tos, walk.StringAtom(i)) } } else { - tos = append(tos, tosStart) + tos = append(tos, walk.StringAtom(tosStart)) } } } else { @@ -217,7 +217,7 @@ func parseSubex(l *RuneReader, minPower int) SubexAST { case '@', '#', '~': lhs = SubexASTCopyAtom{atom: parseTerminatorAtomLiteral(r, l)} default: - lhs = SubexASTCopyAtom{atom: r} + lhs = SubexASTCopyAtom{atom: walk.StringAtom(r)} } loop: for { if minPower <= 0 { diff --git a/walk/walk.go b/walk/walk.go index 36e9805..64f16ac 100644 --- a/walk/walk.go +++ b/walk/walk.go @@ -34,6 +34,7 @@ func (value TerminalValue) String() string { panic("Unknown TerminalValue") } } +func (value TerminalValue) atomness() {} type ValueNull struct {} func (value ValueNull) Pieces(out chan<- Atom) { @@ -42,6 +43,8 @@ func (value ValueNull) Pieces(out chan<- Atom) { func (value ValueNull) String() string { return "null" } +func (value ValueNull) atomness() {} + type ValueBool bool func (value ValueBool) Pieces(out chan<- Atom) { out<-value @@ -53,6 +56,8 @@ func (value ValueBool) String() string { return "false" } } +func (value ValueBool) atomness() {} + type ValueNumber float64 func (value ValueNumber) Pieces(out chan<- Atom) { out<-value @@ -61,14 +66,22 @@ func (value ValueNumber) String() string { v := float64(value) return fmt.Sprintf("%f", v) } +func (value ValueNumber) atomness() {} type StartString struct {} +func (value StartString) atomness() {} + type EndString struct {} +func (value EndString) atomness() {} + +type StringAtom rune +func (value StringAtom) atomness() {} + type ValueString string func (value ValueString) Pieces(out chan<- Atom) { out<-StartString{} for _, char := range value { - out<-char + out<-StringAtom(char) } out<-EndString{} } @@ -76,7 +89,10 @@ func (value ValueString) String() string { return fmt.Sprintf("\"%s\"", string(value)) } -type Atom interface {} +type Atom interface { + // Something so the compiler will check that only certain types are being cast into Atoms + atomness() +} type WalkValue interface { Pieces(out chan<- Atom) @@ -458,7 +474,7 @@ func Compound(in <-chan Atom) <-chan CompoundResult { case ValueNumber: out<-CompoundResult{v, nil} continue - case rune: + case StringAtom: out<-CompoundResult{nil, CompoundRuneOutsideString} break outer case EndString: @@ -480,8 +496,8 @@ func Compound(in <-chan Atom) <-chan CompoundResult { switch v := atom.(type) { case EndString: break loop - case rune: - builder.WriteRune(v) + case StringAtom: + builder.WriteRune(rune(v)) default: out<-CompoundResult{nil, CompoundInvalidStringAtom} break outer -- cgit v1.2.3