From d2dd036d67a4630b8f413ea8982a21489ff47207 Mon Sep 17 00:00:00 2001
From: algochoi <86622919+algochoi@users.noreply.github.com>
Date: Mon, 7 Mar 2022 22:22:55 -0500
Subject: [PATCH 1/8] Start prototype of PC source map
---
cmd/goal/clerk.go | 29 +++++++++++++++++++--
data/transactions/logic/assembler.go | 38 ++++++++++++++++++++++++++++
2 files changed, 65 insertions(+), 2 deletions(-)
diff --git a/cmd/goal/clerk.go b/cmd/goal/clerk.go
index 5359c372ff..3695f3f750 100644
--- a/cmd/goal/clerk.go
+++ b/cmd/goal/clerk.go
@@ -18,6 +18,7 @@ package main
import (
"encoding/base64"
+ "encoding/json"
"fmt"
"io"
"os"
@@ -49,6 +50,7 @@ var (
rejectsFilename string
closeToAddress string
noProgramOutput bool
+ writeSourceMap bool
signProgram bool
programSource string
argB64Strings []string
@@ -123,6 +125,7 @@ func init() {
compileCmd.Flags().BoolVarP(&disassemble, "disassemble", "D", false, "disassemble a compiled program")
compileCmd.Flags().BoolVarP(&noProgramOutput, "no-out", "n", false, "don't write contract program binary")
+ compileCmd.Flags().BoolVarP(&writeSourceMap, "map", "m", false, "write out assembly map")
compileCmd.Flags().BoolVarP(&signProgram, "sign", "s", false, "sign program, output is a binary signed LogicSig record")
compileCmd.Flags().StringVarP(&outFilename, "outfile", "o", "", "Filename to write program bytes or signed LogicSig to")
compileCmd.Flags().StringVarP(&account, "account", "a", "", "Account address to sign the program (If not specified, uses default account)")
@@ -927,7 +930,7 @@ func mustReadFile(fname string) []byte {
return contents
}
-func assembleFile(fname string) (program []byte) {
+func assembleFileImpl(fname string) *logic.OpStream {
text, err := readFile(fname)
if err != nil {
reportErrorf("%s: %s", fname, err)
@@ -948,9 +951,19 @@ func assembleFile(fname string) (program []byte) {
}
}
+ return ops
+}
+
+func assembleFile(fname string) []byte {
+ ops := assembleFileImpl(fname)
return ops.Program
}
+func assembleFileWithMap(fname string) ([]byte, logic.AssemblyMap) {
+ ops := assembleFileImpl(fname)
+ return ops.Program, ops.GetAssemblyMap()
+}
+
func disassembleFile(fname, outname string) {
program, err := readFile(fname)
if err != nil {
@@ -997,7 +1010,7 @@ var compileCmd = &cobra.Command{
disassembleFile(fname, outFilename)
continue
}
- program := assembleFile(fname)
+ program, sourceMap := assembleFileWithMap(fname)
outblob := program
outname := outFilename
if outname == "" {
@@ -1036,6 +1049,18 @@ var compileCmd = &cobra.Command{
reportErrorf("%s: %s", outname, err)
}
}
+ if writeSourceMap {
+ mapname := fname + ".map.json" // TODO: naming?
+ sourceMap.SourceName = fname
+ pcblob, err := json.Marshal(sourceMap)
+ if err != nil {
+ reportErrorf("%s: %s", mapname, err)
+ }
+ err = writeFile(mapname, pcblob, 0666)
+ if err != nil {
+ reportErrorf("%s: %s", mapname, err)
+ }
+ }
if !signProgram && outname != stdoutFilenameValue {
pd := logic.HashProgram(program)
addr := basics.Address(pd)
diff --git a/data/transactions/logic/assembler.go b/data/transactions/logic/assembler.go
index 8202af0bcf..e94524a8df 100644
--- a/data/transactions/logic/assembler.go
+++ b/data/transactions/logic/assembler.go
@@ -272,6 +272,34 @@ func (ops *OpStream) ReferToLabel(pc int, label string) {
ops.labelReferences = append(ops.labelReferences, labelReference{ops.sourceLine, pc, label})
}
+// GetAssemblyMap returns a struct containing details about
+// the assembled file and mappings to the source file
+func (ops *OpStream) GetAssemblyMap() AssemblyMap {
+ maxPC := 0
+ for pc := range ops.OffsetToLine {
+ if pc > maxPC {
+ maxPC = pc
+ }
+ }
+
+ // Array where index is the PC and value is the line.
+ pcToLine := make([]string, maxPC+1)
+ for pc := range pcToLine {
+ if line, ok := ops.OffsetToLine[pc]; ok {
+ pcToLine[pc] = strconv.Itoa(line)
+ } else {
+ pcToLine[pc] = ""
+ }
+ }
+
+ // Encode the source map into a string
+ encodedMapping := strings.Join(pcToLine, ";")
+
+ return AssemblyMap{
+ Mapping: encodedMapping,
+ }
+}
+
type opTypeFunc func(ops *OpStream, immediates []string) (StackTypes, StackTypes)
// returns allows opcodes like `txn` to be specific about their return
@@ -2742,3 +2770,13 @@ func HasStatefulOps(program []byte) (bool, error) {
_, ds, err := disassembleInstrumented(program, nil)
return ds.hasStatefulOps, err
}
+
+// TODO: Consider haing a SourceMapper interface...
+// AssemblyMap contains details from the source to assembly process
+// currently contains map of TEAL source line number to assembled bytecode position
+// and details about the template varirables contained in the source file
+type AssemblyMap struct {
+ SourceName string `json:"source_name"`
+ Mapping string `json:"mapping"`
+ SourceMap []int `json:"source_map"`
+}
From f00862f30f5160525d0116a99b1e5ee7e07639c4 Mon Sep 17 00:00:00 2001
From: algochoi <86622919+algochoi@users.noreply.github.com>
Date: Thu, 17 Mar 2022 14:55:57 -0400
Subject: [PATCH 2/8] Refactor source map struct
---
cmd/goal/clerk.go | 7 ++-
data/transactions/logic/assembler.go | 40 +---------------
data/transactions/logic/sourcemap.go | 68 ++++++++++++++++++++++++++++
3 files changed, 72 insertions(+), 43 deletions(-)
create mode 100644 data/transactions/logic/sourcemap.go
diff --git a/cmd/goal/clerk.go b/cmd/goal/clerk.go
index 3695f3f750..7224a1ab87 100644
--- a/cmd/goal/clerk.go
+++ b/cmd/goal/clerk.go
@@ -959,9 +959,9 @@ func assembleFile(fname string) []byte {
return ops.Program
}
-func assembleFileWithMap(fname string) ([]byte, logic.AssemblyMap) {
+func assembleFileWithMap(fname string) ([]byte, logic.SourceMap) {
ops := assembleFileImpl(fname)
- return ops.Program, ops.GetAssemblyMap()
+ return ops.Program, logic.GetSourceMap([]string{fname}, ops.OffsetToLine)
}
func disassembleFile(fname, outname string) {
@@ -1050,8 +1050,7 @@ var compileCmd = &cobra.Command{
}
}
if writeSourceMap {
- mapname := fname + ".map.json" // TODO: naming?
- sourceMap.SourceName = fname
+ mapname := fname + ".map"
pcblob, err := json.Marshal(sourceMap)
if err != nil {
reportErrorf("%s: %s", mapname, err)
diff --git a/data/transactions/logic/assembler.go b/data/transactions/logic/assembler.go
index e94524a8df..4c09f57030 100644
--- a/data/transactions/logic/assembler.go
+++ b/data/transactions/logic/assembler.go
@@ -267,39 +267,11 @@ func (ops *OpStream) RecordSourceLine() {
ops.OffsetToLine[ops.pending.Len()] = ops.sourceLine - 1
}
-// ReferToLabel records an opcode label refence to resolve later
+// ReferToLabel records an opcode label reference to resolve later
func (ops *OpStream) ReferToLabel(pc int, label string) {
ops.labelReferences = append(ops.labelReferences, labelReference{ops.sourceLine, pc, label})
}
-// GetAssemblyMap returns a struct containing details about
-// the assembled file and mappings to the source file
-func (ops *OpStream) GetAssemblyMap() AssemblyMap {
- maxPC := 0
- for pc := range ops.OffsetToLine {
- if pc > maxPC {
- maxPC = pc
- }
- }
-
- // Array where index is the PC and value is the line.
- pcToLine := make([]string, maxPC+1)
- for pc := range pcToLine {
- if line, ok := ops.OffsetToLine[pc]; ok {
- pcToLine[pc] = strconv.Itoa(line)
- } else {
- pcToLine[pc] = ""
- }
- }
-
- // Encode the source map into a string
- encodedMapping := strings.Join(pcToLine, ";")
-
- return AssemblyMap{
- Mapping: encodedMapping,
- }
-}
-
type opTypeFunc func(ops *OpStream, immediates []string) (StackTypes, StackTypes)
// returns allows opcodes like `txn` to be specific about their return
@@ -2770,13 +2742,3 @@ func HasStatefulOps(program []byte) (bool, error) {
_, ds, err := disassembleInstrumented(program, nil)
return ds.hasStatefulOps, err
}
-
-// TODO: Consider haing a SourceMapper interface...
-// AssemblyMap contains details from the source to assembly process
-// currently contains map of TEAL source line number to assembled bytecode position
-// and details about the template varirables contained in the source file
-type AssemblyMap struct {
- SourceName string `json:"source_name"`
- Mapping string `json:"mapping"`
- SourceMap []int `json:"source_map"`
-}
diff --git a/data/transactions/logic/sourcemap.go b/data/transactions/logic/sourcemap.go
new file mode 100644
index 0000000000..db4af93704
--- /dev/null
+++ b/data/transactions/logic/sourcemap.go
@@ -0,0 +1,68 @@
+// Copyright (C) 2019-2022 Algorand, Inc.
+// This file is part of go-algorand
+//
+// go-algorand is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as
+// published by the Free Software Foundation, either version 3 of the
+// License, or (at your option) any later version.
+//
+// go-algorand is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with go-algorand. If not, see .
+
+package logic
+
+import (
+ "strconv"
+ "strings"
+)
+
+const sourceMapVersion = 3
+
+// SourceMap contains details from the source to assembly process
+// currently contains map of TEAL source line to assembled bytecode position
+// and details about the template variables contained in the source file
+type SourceMap struct {
+ Version int `json:"version"`
+ File string `json:"file"`
+ SourceRoot string `json:"sourceRoot"`
+ Sources []string `json:"sources"`
+ Names []string `json:"names"`
+ Mapping string `json:"mapping"`
+}
+
+// GetSourceMap returns a struct containing details about
+// the assembled file and mappings to the source file.
+func GetSourceMap(sourceNames []string, offsetToLine map[int]int) SourceMap {
+ maxPC := 0
+ for pc := range offsetToLine {
+ if pc > maxPC {
+ maxPC = pc
+ }
+ }
+
+ // Array where index is the PC and value is the line.
+ pcToLine := make([]string, maxPC+1)
+ for pc := range pcToLine {
+ if line, ok := offsetToLine[pc]; ok {
+ pcToLine[pc] = strconv.Itoa(line)
+ } else {
+ pcToLine[pc] = ""
+ }
+ }
+
+ // Encode the source map into a string
+ encodedMapping := strings.Join(pcToLine, ";")
+
+ return SourceMap{
+ Version: sourceMapVersion,
+ File: "", // Assembled file does not have a name.
+ Sources: sourceNames,
+ Names: []string{}, // TEAL code does not generate any names
+ Mapping: encodedMapping,
+ }
+}
From 9279f9cae2c2e7da8954f031c3400df256cf5a65 Mon Sep 17 00:00:00 2001
From: algochoi <86622919+algochoi@users.noreply.github.com>
Date: Mon, 28 Mar 2022 14:29:58 -0400
Subject: [PATCH 3/8] Add some tests for source maps
---
data/transactions/logic/sourcemap.go | 34 ++++++++++--
data/transactions/logic/sourcemap_test.go | 63 +++++++++++++++++++++++
2 files changed, 93 insertions(+), 4 deletions(-)
create mode 100644 data/transactions/logic/sourcemap_test.go
diff --git a/data/transactions/logic/sourcemap.go b/data/transactions/logic/sourcemap.go
index db4af93704..1e5277c5fe 100644
--- a/data/transactions/logic/sourcemap.go
+++ b/data/transactions/logic/sourcemap.go
@@ -17,11 +17,13 @@
package logic
import (
- "strconv"
+ "bytes"
"strings"
)
+// sourceMapVersion is currently 3: https://sourcemaps.info/spec.html
const sourceMapVersion = 3
+const b64table string = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
// SourceMap contains details from the source to assembly process
// currently contains map of TEAL source line to assembled bytecode position
@@ -36,7 +38,7 @@ type SourceMap struct {
}
// GetSourceMap returns a struct containing details about
-// the assembled file and mappings to the source file.
+// the assembled file and encoded mappings to the source file.
func GetSourceMap(sourceNames []string, offsetToLine map[int]int) SourceMap {
maxPC := 0
for pc := range offsetToLine {
@@ -49,7 +51,7 @@ func GetSourceMap(sourceNames []string, offsetToLine map[int]int) SourceMap {
pcToLine := make([]string, maxPC+1)
for pc := range pcToLine {
if line, ok := offsetToLine[pc]; ok {
- pcToLine[pc] = strconv.Itoa(line)
+ pcToLine[pc] = MakeSourceMapLine(0, 0, line, 0)
} else {
pcToLine[pc] = ""
}
@@ -62,7 +64,31 @@ func GetSourceMap(sourceNames []string, offsetToLine map[int]int) SourceMap {
Version: sourceMapVersion,
File: "", // Assembled file does not have a name.
Sources: sourceNames,
- Names: []string{}, // TEAL code does not generate any names
+ Names: []string{}, // TEAL code does not generate any names.
Mapping: encodedMapping,
}
}
+
+// IntToVLQ writes out value to bytes.Buffer
+func IntToVLQ(v int, buf *bytes.Buffer) {
+ v <<= 1
+ if v < 0 {
+ v = -v
+ v |= 1
+ }
+ for v >= 32 {
+ buf.WriteByte(b64table[32|(v&31)])
+ v >>= 5
+ }
+ buf.WriteByte(b64table[v])
+}
+
+// MakeSourceMapLine creates source map mapping's line entry
+func MakeSourceMapLine(tcol, sindex, sline, scol int) string {
+ buf := bytes.NewBuffer(nil)
+ IntToVLQ(tcol, buf)
+ IntToVLQ(sindex, buf)
+ IntToVLQ(sline, buf)
+ IntToVLQ(scol, buf)
+ return buf.String()
+}
diff --git a/data/transactions/logic/sourcemap_test.go b/data/transactions/logic/sourcemap_test.go
new file mode 100644
index 0000000000..a60f00c23e
--- /dev/null
+++ b/data/transactions/logic/sourcemap_test.go
@@ -0,0 +1,63 @@
+// Copyright (C) 2019-2022 Algorand, Inc.
+// This file is part of go-algorand
+//
+// go-algorand is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as
+// published by the Free Software Foundation, either version 3 of the
+// License, or (at your option) any later version.
+//
+// go-algorand is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with go-algorand. If not, see .
+
+package logic
+
+import (
+ "strings"
+ "testing"
+
+ "github.com/algorand/go-algorand/test/partitiontest"
+ "github.com/stretchr/testify/require"
+)
+
+func TestGetSourceMap(t *testing.T) {
+ partitiontest.PartitionTest(t)
+ a := require.New(t)
+
+ sourceNames := []string{"test.teal"}
+ offsetToLine := map[int]int{
+ 1: 1,
+ 2: 2,
+ 3: 5,
+ }
+ actualSourceMap := GetSourceMap(sourceNames, offsetToLine)
+
+ a.Equal(sourceMapVersion, actualSourceMap.Version)
+ a.Equal("", actualSourceMap.File)
+ a.Equal(sourceNames, actualSourceMap.Sources)
+ a.Equal([]string{}, actualSourceMap.Names)
+
+ // Check encoding for each line.
+ splitMapping := strings.Split(actualSourceMap.Mapping, ";")
+ for pc := range splitMapping {
+ if line, ok := offsetToLine[pc]; ok {
+ a.Equal(MakeSourceMapLine(0, 0, line, 0), splitMapping[pc])
+ }
+ }
+}
+
+func TestVLQ(t *testing.T) {
+ partitiontest.PartitionTest(t)
+ a := require.New(t)
+
+ a.Equal("AAAA", MakeSourceMapLine(0, 0, 0, 0))
+ a.Equal("AACA", MakeSourceMapLine(0, 0, 1, 0))
+ a.Equal("AAEA", MakeSourceMapLine(0, 0, 2, 0))
+ a.Equal("AAgBA", MakeSourceMapLine(0, 0, 16, 0))
+ a.Equal("AAggBA", MakeSourceMapLine(0, 0, 512, 0))
+ a.Equal("ADggBD", MakeSourceMapLine(0, -1, 512, -1))
+}
From bf9fc027cfee9e5775035da31074fa3b2f6a680a Mon Sep 17 00:00:00 2001
From: algochoi <86622919+algochoi@users.noreply.github.com>
Date: Thu, 14 Apr 2022 16:36:07 -0400
Subject: [PATCH 4/8] Move VLQ encoding into logic package and delete in
tealdbg dir
---
cmd/tealdbg/util.go | 26 ++++++--------------------
cmd/tealdbg/util_test.go | 36 ------------------------------------
2 files changed, 6 insertions(+), 56 deletions(-)
delete mode 100644 cmd/tealdbg/util_test.go
diff --git a/cmd/tealdbg/util.go b/cmd/tealdbg/util.go
index 6a7f880efb..40c1c85060 100644
--- a/cmd/tealdbg/util.go
+++ b/cmd/tealdbg/util.go
@@ -20,6 +20,8 @@ import (
"bytes"
"strconv"
"sync/atomic"
+
+ "github.com/algorand/go-algorand/data/transactions/logic"
)
type atomicString struct {
@@ -101,28 +103,12 @@ func IsTextFile(data []byte) bool {
return printable
}
-const b64table string = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
-
-// IntToVLQ writes out value to bytes.Buffer
-func IntToVLQ(v int, buf *bytes.Buffer) {
- v <<= 1
- if v < 0 {
- v = -v
- v |= 1
- }
- for v >= 32 {
- buf.WriteByte(b64table[32|(v&31)])
- v >>= 5
- }
- buf.WriteByte(b64table[v])
-}
-
// MakeSourceMapLine creates source map mapping's line entry
func MakeSourceMapLine(tcol, sindex, sline, scol int) string {
buf := bytes.NewBuffer(nil)
- IntToVLQ(tcol, buf)
- IntToVLQ(sindex, buf)
- IntToVLQ(sline, buf)
- IntToVLQ(scol, buf)
+ logic.IntToVLQ(tcol, buf)
+ logic.IntToVLQ(sindex, buf)
+ logic.IntToVLQ(sline, buf)
+ logic.IntToVLQ(scol, buf)
return buf.String()
}
diff --git a/cmd/tealdbg/util_test.go b/cmd/tealdbg/util_test.go
deleted file mode 100644
index 85de0747dd..0000000000
--- a/cmd/tealdbg/util_test.go
+++ /dev/null
@@ -1,36 +0,0 @@
-// Copyright (C) 2019-2022 Algorand, Inc.
-// This file is part of go-algorand
-//
-// go-algorand is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Affero General Public License as
-// published by the Free Software Foundation, either version 3 of the
-// License, or (at your option) any later version.
-//
-// go-algorand is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Affero General Public License for more details.
-//
-// You should have received a copy of the GNU Affero General Public License
-// along with go-algorand. If not, see .
-
-package main
-
-import (
- "testing"
-
- "github.com/algorand/go-algorand/test/partitiontest"
- "github.com/stretchr/testify/require"
-)
-
-func TestVLQ(t *testing.T) {
- partitiontest.PartitionTest(t)
- a := require.New(t)
-
- a.Equal("AAAA", MakeSourceMapLine(0, 0, 0, 0))
- a.Equal("AACA", MakeSourceMapLine(0, 0, 1, 0))
- a.Equal("AAEA", MakeSourceMapLine(0, 0, 2, 0))
- a.Equal("AAgBA", MakeSourceMapLine(0, 0, 16, 0))
- a.Equal("AAggBA", MakeSourceMapLine(0, 0, 512, 0))
- a.Equal("ADggBD", MakeSourceMapLine(0, -1, 512, -1))
-}
From 6ddc4d11f2e65262f2d942ef3c36057ff98f5164 Mon Sep 17 00:00:00 2001
From: algochoi <86622919+algochoi@users.noreply.github.com>
Date: Thu, 14 Apr 2022 17:05:40 -0400
Subject: [PATCH 5/8] Remove redundant function in tealdbg
---
cmd/tealdbg/debugger.go | 6 +++---
cmd/tealdbg/util.go | 13 -------------
data/transactions/logic/sourcemap.go | 12 ++++++------
3 files changed, 9 insertions(+), 22 deletions(-)
diff --git a/cmd/tealdbg/debugger.go b/cmd/tealdbg/debugger.go
index 34957f2c7b..b9b8995609 100644
--- a/cmd/tealdbg/debugger.go
+++ b/cmd/tealdbg/debugger.go
@@ -368,14 +368,14 @@ func (s *session) GetSourceMap() ([]byte, error) {
prevSourceLine := 0
// the very first entry is needed by CDT
- lines[0] = MakeSourceMapLine(targetCol, sourceIdx, 0, sourceCol)
+ lines[0] = logic.MakeSourceMapLine(targetCol, sourceIdx, 0, sourceCol)
for targetLine := 1; targetLine < len(s.lines); targetLine++ {
if pc, ok := s.pcOffset[targetLine]; ok && pc != 0 {
sourceLine, ok = s.offsetToLine[pc]
if !ok {
lines[targetLine] = ""
} else {
- lines[targetLine] = MakeSourceMapLine(targetCol, sourceIdx, sourceLine-prevSourceLine, sourceCol)
+ lines[targetLine] = logic.MakeSourceMapLine(targetCol, sourceIdx, sourceLine-prevSourceLine, sourceCol)
prevSourceLine = sourceLine
}
} else {
@@ -384,7 +384,7 @@ func (s *session) GetSourceMap() ([]byte, error) {
if targetLine == len(s.lines)-1 {
delta = 1
}
- lines[targetLine] = MakeSourceMapLine(targetCol, sourceIdx, delta, sourceCol)
+ lines[targetLine] = logic.MakeSourceMapLine(targetCol, sourceIdx, delta, sourceCol)
}
}
diff --git a/cmd/tealdbg/util.go b/cmd/tealdbg/util.go
index 40c1c85060..d611c7bcb1 100644
--- a/cmd/tealdbg/util.go
+++ b/cmd/tealdbg/util.go
@@ -17,11 +17,8 @@
package main
import (
- "bytes"
"strconv"
"sync/atomic"
-
- "github.com/algorand/go-algorand/data/transactions/logic"
)
type atomicString struct {
@@ -102,13 +99,3 @@ func IsTextFile(data []byte) bool {
}
return printable
}
-
-// MakeSourceMapLine creates source map mapping's line entry
-func MakeSourceMapLine(tcol, sindex, sline, scol int) string {
- buf := bytes.NewBuffer(nil)
- logic.IntToVLQ(tcol, buf)
- logic.IntToVLQ(sindex, buf)
- logic.IntToVLQ(sline, buf)
- logic.IntToVLQ(scol, buf)
- return buf.String()
-}
diff --git a/data/transactions/logic/sourcemap.go b/data/transactions/logic/sourcemap.go
index 1e5277c5fe..c8b0270cf9 100644
--- a/data/transactions/logic/sourcemap.go
+++ b/data/transactions/logic/sourcemap.go
@@ -69,8 +69,8 @@ func GetSourceMap(sourceNames []string, offsetToLine map[int]int) SourceMap {
}
}
-// IntToVLQ writes out value to bytes.Buffer
-func IntToVLQ(v int, buf *bytes.Buffer) {
+// intToVLQ writes out value to bytes.Buffer
+func intToVLQ(v int, buf *bytes.Buffer) {
v <<= 1
if v < 0 {
v = -v
@@ -86,9 +86,9 @@ func IntToVLQ(v int, buf *bytes.Buffer) {
// MakeSourceMapLine creates source map mapping's line entry
func MakeSourceMapLine(tcol, sindex, sline, scol int) string {
buf := bytes.NewBuffer(nil)
- IntToVLQ(tcol, buf)
- IntToVLQ(sindex, buf)
- IntToVLQ(sline, buf)
- IntToVLQ(scol, buf)
+ intToVLQ(tcol, buf)
+ intToVLQ(sindex, buf)
+ intToVLQ(sline, buf)
+ intToVLQ(scol, buf)
return buf.String()
}
From 6645cb5eebaecb7476ff4849ad6573d25f8c74c5 Mon Sep 17 00:00:00 2001
From: algochoi <86622919+algochoi@users.noreply.github.com>
Date: Fri, 15 Apr 2022 14:39:10 -0400
Subject: [PATCH 6/8] Fix some tests and mark some fields as optional
---
cmd/goal/clerk.go | 2 +-
data/transactions/logic/sourcemap.go | 15 ++++++++-------
data/transactions/logic/sourcemap_test.go | 5 +++--
3 files changed, 12 insertions(+), 10 deletions(-)
diff --git a/cmd/goal/clerk.go b/cmd/goal/clerk.go
index dac6f639e1..987c14a316 100644
--- a/cmd/goal/clerk.go
+++ b/cmd/goal/clerk.go
@@ -125,7 +125,7 @@ func init() {
compileCmd.Flags().BoolVarP(&disassemble, "disassemble", "D", false, "disassemble a compiled program")
compileCmd.Flags().BoolVarP(&noProgramOutput, "no-out", "n", false, "don't write contract program binary")
- compileCmd.Flags().BoolVarP(&writeSourceMap, "map", "m", false, "write out assembly map")
+ compileCmd.Flags().BoolVarP(&writeSourceMap, "map", "m", false, "write out source map")
compileCmd.Flags().BoolVarP(&signProgram, "sign", "s", false, "sign program, output is a binary signed LogicSig record")
compileCmd.Flags().StringVarP(&outFilename, "outfile", "o", "", "Filename to write program bytes or signed LogicSig to")
compileCmd.Flags().StringVarP(&account, "account", "a", "", "Account address to sign the program (If not specified, uses default account)")
diff --git a/data/transactions/logic/sourcemap.go b/data/transactions/logic/sourcemap.go
index c8b0270cf9..3ffafd5e50 100644
--- a/data/transactions/logic/sourcemap.go
+++ b/data/transactions/logic/sourcemap.go
@@ -21,17 +21,19 @@ import (
"strings"
)
-// sourceMapVersion is currently 3: https://sourcemaps.info/spec.html
+// sourceMapVersion is currently 3.
+// Refer to the full specs of sourcemap here: https://sourcemaps.info/spec.html
const sourceMapVersion = 3
const b64table string = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
-// SourceMap contains details from the source to assembly process
-// currently contains map of TEAL source line to assembled bytecode position
-// and details about the template variables contained in the source file
+// SourceMap contains details from the source to assembly process.
+// Currently contains the map between TEAL source line to
+// the assembled bytecode position and details about
+// the template variables contained in the source file.
type SourceMap struct {
Version int `json:"version"`
- File string `json:"file"`
- SourceRoot string `json:"sourceRoot"`
+ File string `json:"file,omitempty"`
+ SourceRoot string `json:"sourceRoot,omitempty"`
Sources []string `json:"sources"`
Names []string `json:"names"`
Mapping string `json:"mapping"`
@@ -62,7 +64,6 @@ func GetSourceMap(sourceNames []string, offsetToLine map[int]int) SourceMap {
return SourceMap{
Version: sourceMapVersion,
- File: "", // Assembled file does not have a name.
Sources: sourceNames,
Names: []string{}, // TEAL code does not generate any names.
Mapping: encodedMapping,
diff --git a/data/transactions/logic/sourcemap_test.go b/data/transactions/logic/sourcemap_test.go
index a60f00c23e..718535ec44 100644
--- a/data/transactions/logic/sourcemap_test.go
+++ b/data/transactions/logic/sourcemap_test.go
@@ -32,12 +32,11 @@ func TestGetSourceMap(t *testing.T) {
offsetToLine := map[int]int{
1: 1,
2: 2,
- 3: 5,
+ 5: 3,
}
actualSourceMap := GetSourceMap(sourceNames, offsetToLine)
a.Equal(sourceMapVersion, actualSourceMap.Version)
- a.Equal("", actualSourceMap.File)
a.Equal(sourceNames, actualSourceMap.Sources)
a.Equal([]string{}, actualSourceMap.Names)
@@ -46,6 +45,8 @@ func TestGetSourceMap(t *testing.T) {
for pc := range splitMapping {
if line, ok := offsetToLine[pc]; ok {
a.Equal(MakeSourceMapLine(0, 0, line, 0), splitMapping[pc])
+ } else {
+ a.Equal("", splitMapping[pc])
}
}
}
From 17d9b9c7f7eeb9c3c2503912bd3815062514948f Mon Sep 17 00:00:00 2001
From: algochoi <86622919+algochoi@users.noreply.github.com>
Date: Tue, 19 Apr 2022 18:08:33 -0400
Subject: [PATCH 7/8] Add e2e shell test and fix typo in existing test
---
data/transactions/logic/tlhc.py | 4 ++--
test/scripts/e2e_subs/e2e-teal.sh | 14 ++++++++++++++
test/scripts/e2e_subs/tealprogs/quine.map | 1 +
3 files changed, 17 insertions(+), 2 deletions(-)
create mode 100644 test/scripts/e2e_subs/tealprogs/quine.map
diff --git a/data/transactions/logic/tlhc.py b/data/transactions/logic/tlhc.py
index f436b78100..ce8c8d793e 100755
--- a/data/transactions/logic/tlhc.py
+++ b/data/transactions/logic/tlhc.py
@@ -69,11 +69,11 @@ def main():
out.write(code)
try:
out.close()
- except Exeption as e:
+ except Exception as e:
print(e)
try:
secretout.close()
- except Exeption as e:
+ except Exception as e:
print(e)
return
diff --git a/test/scripts/e2e_subs/e2e-teal.sh b/test/scripts/e2e_subs/e2e-teal.sh
index a71c78a10d..da13d30715 100755
--- a/test/scripts/e2e_subs/e2e-teal.sh
+++ b/test/scripts/e2e_subs/e2e-teal.sh
@@ -11,6 +11,8 @@ WALLET=$1
gcmd="goal -w ${WALLET}"
+TEAL=test/scripts/e2e_subs/tealprogs
+
ACCOUNT=$(${gcmd} account list|awk '{ print $3 }')
# prints:
@@ -148,6 +150,18 @@ ${gcmd} clerk compile ${TEMPDIR}/true3.teal -o ${TEMPDIR}/true3.lsig
cp ${TEMPDIR}/true3.lsig ${TEMPDIR}/true2.lsig
printf '\x02' | dd of=${TEMPDIR}/true2.lsig bs=1 seek=0 count=1 conv=notrunc
+# Try to compile with source map, and check that map is correct.
+# Since the source map contains info about the file path,
+# we need to do this in place and clean up the file later.
+${gcmd} clerk compile ${TEAL}/quine.teal -m
+if ! diff ${TEAL}/quine.map ${TEAL}/quine.teal.map > /dev/null; then
+ rm ${TEAL}/quine.teal.*
+ echo "produced source maps do not match"
+ exit 1
+fi
+# Clean up generated source map
+rm ${TEAL}/quine.teal.*
+
# compute the escrow account for the frankenstein program
ACCOUNT_TRUE=$(python -c 'import algosdk, sys; print(algosdk.logic.address(sys.stdin.buffer.read()))' < ${TEMPDIR}/true2.lsig)
# fund that escrow account
diff --git a/test/scripts/e2e_subs/tealprogs/quine.map b/test/scripts/e2e_subs/tealprogs/quine.map
new file mode 100644
index 0000000000..02e426d14b
--- /dev/null
+++ b/test/scripts/e2e_subs/tealprogs/quine.map
@@ -0,0 +1 @@
+{"version":3,"sources":["test/scripts/e2e_subs/tealprogs/quine.teal"],"names":[],"mapping":";AAOA;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAQA;AASA;;;AAUA;;;AAWA;AAYA;;AAaA;AAcA;;;AAeA;AAgBA;AAiBA;;AAkBA;;AAmBA;AAoBA;AAqBA"}
\ No newline at end of file
From 21aa4a13d2b48f01558773fec1a2035317a856ae Mon Sep 17 00:00:00 2001
From: algochoi <86622919+algochoi@users.noreply.github.com>
Date: Wed, 20 Apr 2022 10:41:32 -0400
Subject: [PATCH 8/8] Retain diff and use trap to clean up test files
---
test/scripts/e2e_subs/e2e-teal.sh | 8 +++-----
1 file changed, 3 insertions(+), 5 deletions(-)
diff --git a/test/scripts/e2e_subs/e2e-teal.sh b/test/scripts/e2e_subs/e2e-teal.sh
index da13d30715..93cb408896 100755
--- a/test/scripts/e2e_subs/e2e-teal.sh
+++ b/test/scripts/e2e_subs/e2e-teal.sh
@@ -152,15 +152,13 @@ printf '\x02' | dd of=${TEMPDIR}/true2.lsig bs=1 seek=0 count=1 conv=notrunc
# Try to compile with source map, and check that map is correct.
# Since the source map contains info about the file path,
-# we need to do this in place and clean up the file later.
+# we do this in place and clean up the file later.
${gcmd} clerk compile ${TEAL}/quine.teal -m
-if ! diff ${TEAL}/quine.map ${TEAL}/quine.teal.map > /dev/null; then
- rm ${TEAL}/quine.teal.*
+trap 'rm ${TEAL}/quine.teal.*' EXIT
+if ! diff ${TEAL}/quine.map ${TEAL}/quine.teal.map; then
echo "produced source maps do not match"
exit 1
fi
-# Clean up generated source map
-rm ${TEAL}/quine.teal.*
# compute the escrow account for the frankenstein program
ACCOUNT_TRUE=$(python -c 'import algosdk, sys; print(algosdk.logic.address(sys.stdin.buffer.read()))' < ${TEMPDIR}/true2.lsig)