Something went wrong. Try again.
A native-speed rewrite of the roblox-ts compiler in golang
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254package sourcemap
import ( "errors" "iter"
"rotor/tsgo/core")
type Mapping struct { GeneratedLine int GeneratedCharacter core.UTF16Offset SourceIndex SourceIndex SourceLine int SourceCharacter core.UTF16Offset NameIndex NameIndex}
func (m *Mapping) Equals(other *Mapping) bool { return m == other || m.GeneratedLine == other.GeneratedLine && m.GeneratedCharacter == other.GeneratedCharacter && m.SourceIndex == other.SourceIndex && m.SourceLine == other.SourceLine && m.SourceCharacter == other.SourceCharacter && m.NameIndex == other.NameIndex}
func (m *Mapping) IsSourceMapping() bool { return m.SourceIndex != MissingSource && m.SourceLine != MissingLineOrColumn && m.SourceCharacter != MissingUTF16Column}
const ( MissingSource SourceIndex = -1 MissingName NameIndex = -1 MissingLineOrColumn int = -1 MissingUTF16Column core.UTF16Offset = -1)
type MappingsDecoder struct { mappings string done bool pos int generatedLine int generatedCharacter core.UTF16Offset sourceIndex SourceIndex sourceLine int sourceCharacter core.UTF16Offset nameIndex NameIndex error error mappingArena core.Arena[Mapping]}
func DecodeMappings(mappings string) *MappingsDecoder { return &MappingsDecoder{mappings: mappings}}
func (d *MappingsDecoder) MappingsString() string { return d.mappings}
func (d *MappingsDecoder) Pos() int { return d.pos}
func (d *MappingsDecoder) Error() error { return d.error}
func (d *MappingsDecoder) State() *Mapping { return d.captureMapping(true /*hasSource*/, true /*hasName*/)}
func (d *MappingsDecoder) Values() iter.Seq[*Mapping] { return func(yield func(*Mapping) bool) { for value, done := d.Next(); !done; value, done = d.Next() { if !yield(value) { break } } }}
func (d *MappingsDecoder) Next() (value *Mapping, done bool) { for !d.done && d.pos < len(d.mappings) { ch := d.mappings[d.pos] if ch == ';' { // new line d.generatedLine++ d.generatedCharacter = 0 d.pos++ continue }
if ch == ',' { // Next entry is on same line - no action needed d.pos++ continue }
hasSource := false hasName := false d.generatedCharacter += core.UTF16Offset(d.base64VLQFormatDecode()) if d.hasReportedError() { return d.stopIterating() } if d.generatedCharacter < 0 { return d.setErrorAndStopIterating("Invalid generatedCharacter found") }
if !d.isSourceMappingSegmentEnd() { hasSource = true
d.sourceIndex += SourceIndex(d.base64VLQFormatDecode()) if d.hasReportedError() { return d.stopIterating() } if d.sourceIndex < 0 { return d.setErrorAndStopIterating("Invalid sourceIndex found") } if d.isSourceMappingSegmentEnd() { return d.setErrorAndStopIterating("Unsupported Format: No entries after sourceIndex") }
d.sourceLine += d.base64VLQFormatDecode() if d.hasReportedError() { return d.stopIterating() } if d.sourceLine < 0 { return d.setErrorAndStopIterating("Invalid sourceLine found") } if d.isSourceMappingSegmentEnd() { return d.setErrorAndStopIterating("Unsupported Format: No entries after sourceLine") }
d.sourceCharacter += core.UTF16Offset(d.base64VLQFormatDecode()) if d.hasReportedError() { return d.stopIterating() } if d.sourceCharacter < 0 { return d.setErrorAndStopIterating("Invalid sourceCharacter found") }
if !d.isSourceMappingSegmentEnd() { hasName = true d.nameIndex += NameIndex(d.base64VLQFormatDecode()) if d.hasReportedError() { return d.stopIterating() } if d.nameIndex < 0 { return d.setErrorAndStopIterating("Invalid nameIndex found") }
if !d.isSourceMappingSegmentEnd() { return d.setErrorAndStopIterating("Unsupported Error Format: Entries after nameIndex") } } }
return d.captureMapping(hasSource, hasName), false }
return d.stopIterating()}
func (d *MappingsDecoder) captureMapping(hasSource bool, hasName bool) *Mapping { mapping := d.mappingArena.New() mapping.GeneratedLine = d.generatedLine mapping.GeneratedCharacter = d.generatedCharacter mapping.SourceIndex = core.IfElse(hasSource, d.sourceIndex, MissingSource) mapping.SourceLine = core.IfElse(hasSource, d.sourceLine, MissingLineOrColumn) mapping.SourceCharacter = core.IfElse(hasSource, d.sourceCharacter, MissingUTF16Column) mapping.NameIndex = core.IfElse(hasName, d.nameIndex, MissingName) return mapping}
func (d *MappingsDecoder) stopIterating() (*Mapping, bool) { d.done = true return nil, true}
func (d *MappingsDecoder) setError(err string) { d.error = errors.New(err)}
func (d *MappingsDecoder) setErrorAndStopIterating(err string) (*Mapping, bool) { d.setError(err) return d.stopIterating()}
func (d *MappingsDecoder) hasReportedError() bool { return d.error != nil}
func (d *MappingsDecoder) isSourceMappingSegmentEnd() bool { return d.pos == len(d.mappings) || d.mappings[d.pos] == ',' || d.mappings[d.pos] == ';'}
func (d *MappingsDecoder) base64VLQFormatDecode() int { moreDigits := true shiftCount := 0 value := 0 for ; moreDigits; d.pos++ { if d.pos >= len(d.mappings) { d.setError("Error in decoding base64VLQFormatDecode, past the mapping string") return -1 }
// 6 digit number currentByte := base64FormatDecode(d.mappings[d.pos]) if currentByte == -1 { d.setError("Invalid character in VLQ") return -1 }
// If msb is set, we still have more bits to continue moreDigits = (currentByte & 32) != 0
// least significant 5 bits are the next msbs in the final value. value = value | ((currentByte & 31) << shiftCount) shiftCount += 5 }
// Least significant bit if 1 represents negative and rest of the msb is actual absolute value if (value & 1) == 0 { // + number value = value >> 1 } else { // - number value = value >> 1 value = -value }
return value}
func base64FormatDecode(ch byte) int { switch { case ch >= 'A' && ch <= 'Z': return int(ch - 'A') case ch >= 'a' && ch <= 'z': return int(ch - 'a' + 26) case ch >= '0' && ch <= '9': return int(ch - '0' + 52) case ch == '+': return 62 case ch == '/': return 63 default: return -1 }}