summaryrefslogtreecommitdiff
path: root/cmd/opdoc/opdoc.go
diff options
context:
space:
mode:
Diffstat (limited to 'cmd/opdoc/opdoc.go')
-rw-r--r--cmd/opdoc/opdoc.go226
1 files changed, 124 insertions, 102 deletions
diff --git a/cmd/opdoc/opdoc.go b/cmd/opdoc/opdoc.go
index be9b69956..c98a1a0f7 100644
--- a/cmd/opdoc/opdoc.go
+++ b/cmd/opdoc/opdoc.go
@@ -29,8 +29,8 @@ import (
)
func opGroupMarkdownTable(names []string, out io.Writer) {
- fmt.Fprint(out, `| Op | Description |
-| --- | --- |
+ fmt.Fprint(out, `| Opcode | Description |
+| - | -- |
`)
opSpecs := logic.OpsByName[logic.LogicVersion]
// TODO: sort by logic.OpSpecs[].Opcode
@@ -58,69 +58,98 @@ func typeEnumTableMarkdown(out io.Writer) {
func integerConstantsTableMarkdown(out io.Writer) {
fmt.Fprintf(out, "#### OnComplete\n\n")
fmt.Fprintf(out, "%s\n\n", logic.OnCompletionPreamble)
- fmt.Fprintf(out, "| Value | Constant name | Description |\n")
- fmt.Fprintf(out, "| --- | --- | --- |\n")
+ fmt.Fprintf(out, "| Value | Name | Description |\n")
+ fmt.Fprintf(out, "| - | ---- | -------- |\n")
for i, name := range logic.OnCompletionNames {
value := uint64(i)
fmt.Fprintf(out, "| %d | %s | %s |\n", value, markdownTableEscape(name), logic.OnCompletionDescription(value))
}
fmt.Fprintf(out, "\n")
- fmt.Fprintf(out, "#### TypeEnum constants\n")
- fmt.Fprintf(out, "| Value | Constant name | Description |\n")
- fmt.Fprintf(out, "| --- | --- | --- |\n")
+ fmt.Fprintf(out, "#### TypeEnum constants\n\n")
+ fmt.Fprintf(out, "| Value | Name | Description |\n")
+ fmt.Fprintf(out, "| - | --- | ------ |\n")
for i, name := range logic.TxnTypeNames {
fmt.Fprintf(out, "| %d | %s | %s |\n", i, markdownTableEscape(name), logic.TypeNameDescriptions[name])
}
out.Write([]byte("\n"))
}
-func fieldTableMarkdown(out io.Writer, names []string, types []logic.StackType, extra map[string]string) {
- if types != nil {
- fmt.Fprintf(out, "| Index | Name | Type | Notes |\n")
- fmt.Fprintf(out, "| --- | --- | --- | --- |\n")
- } else {
- fmt.Fprintf(out, "| Index | Name | Notes |\n")
- fmt.Fprintf(out, "| --- | --- | --- |\n")
+type speccer interface {
+ SpecByName(name string) logic.FieldSpec
+}
+
+func fieldSpecsMarkdown(out io.Writer, names []string, specs speccer) {
+ showTypes := false
+ showVers := false
+ spec0 := specs.SpecByName(names[0])
+ opVer := spec0.OpVersion()
+ for _, name := range names {
+ if specs.SpecByName(name).Type() != logic.StackNone {
+ showTypes = true
+ }
+ if specs.SpecByName(name).Version() != opVer {
+ showVers = true
+ }
+ }
+ headers := "| Index | Name |"
+ widths := "| - | ------ |"
+ if showTypes {
+ headers += " Type |"
+ widths += " -- |"
+ }
+ if showVers {
+ headers += " In |"
+ widths += " - |"
}
+ headers += " Notes |\n"
+ widths += " --------- |\n"
+ fmt.Fprint(out, headers, widths)
for i, name := range names {
+ spec := specs.SpecByName(name)
str := fmt.Sprintf("| %d | %s", i, markdownTableEscape(name))
- if types != nil {
- gfType := types[i]
- str = fmt.Sprintf("%s | %s", str, markdownTableEscape(gfType.String()))
+ if showTypes {
+ str = fmt.Sprintf("%s | %s", str, markdownTableEscape(spec.Type().String()))
+ }
+ if showVers {
+ if spec.Version() == spec.OpVersion() {
+ str = fmt.Sprintf("%s | ", str)
+ } else {
+ str = fmt.Sprintf("%s | v%d ", str, spec.Version())
+ }
}
- fmt.Fprintf(out, "%s | %s |\n", str, extra[name])
+ fmt.Fprintf(out, "%s | %s |\n", str, spec.Note())
}
- out.Write([]byte("\n"))
+ fmt.Fprint(out, "\n")
}
func transactionFieldsMarkdown(out io.Writer) {
fmt.Fprintf(out, "\n`txn` Fields (see [transaction reference](https://developer.algorand.org/docs/reference/transactions/)):\n\n")
- fieldTableMarkdown(out, logic.TxnFieldNames, logic.TxnFieldTypes, logic.TxnFieldDocs())
+ fieldSpecsMarkdown(out, logic.TxnFieldNames, logic.TxnFieldSpecByName)
}
func globalFieldsMarkdown(out io.Writer) {
fmt.Fprintf(out, "\n`global` Fields:\n\n")
- fieldTableMarkdown(out, logic.GlobalFieldNames, logic.GlobalFieldTypes, logic.GlobalFieldDocs())
+ fieldSpecsMarkdown(out, logic.GlobalFieldNames, logic.GlobalFieldSpecByName)
}
func assetHoldingFieldsMarkdown(out io.Writer) {
fmt.Fprintf(out, "\n`asset_holding_get` Fields:\n\n")
- fieldTableMarkdown(out, logic.AssetHoldingFieldNames, logic.AssetHoldingFieldTypes, logic.AssetHoldingFieldDocs)
+ fieldSpecsMarkdown(out, logic.AssetHoldingFieldNames, logic.AssetHoldingFieldSpecByName)
}
func assetParamsFieldsMarkdown(out io.Writer) {
fmt.Fprintf(out, "\n`asset_params_get` Fields:\n\n")
- fieldTableMarkdown(out, logic.AssetParamsFieldNames, logic.AssetParamsFieldTypes, logic.AssetParamsFieldDocs())
+ fieldSpecsMarkdown(out, logic.AssetParamsFieldNames, logic.AssetParamsFieldSpecByName)
}
func appParamsFieldsMarkdown(out io.Writer) {
fmt.Fprintf(out, "\n`app_params_get` Fields:\n\n")
- fieldTableMarkdown(out, logic.AppParamsFieldNames, logic.AppParamsFieldTypes, logic.AppParamsFieldDocs())
+ fieldSpecsMarkdown(out, logic.AppParamsFieldNames, logic.AppParamsFieldSpecByName)
}
func ecDsaCurvesMarkdown(out io.Writer) {
fmt.Fprintf(out, "\n`ECDSA` Curves:\n\n")
- fieldTableMarkdown(out, logic.EcdsaCurveNames, nil, logic.EcdsaCurveDocs)
+ fieldSpecsMarkdown(out, logic.EcdsaCurveNames, logic.EcdsaCurveSpecByName)
}
func immediateMarkdown(op *logic.OpSpec) string {
@@ -131,38 +160,45 @@ func immediateMarkdown(op *logic.OpSpec) string {
return markdown
}
-func opToMarkdown(out io.Writer, op *logic.OpSpec) (err error) {
- ws := ""
- opextra := logic.OpImmediateNote(op.Name)
- if opextra != "" {
- ws = " "
+func stackMarkdown(op *logic.OpSpec) string {
+ out := "- Stack: "
+ special := logic.OpStackEffects(op.Name)
+ if special != "" {
+ return out + special + "\n"
}
- fmt.Fprintf(out, "\n## %s%s\n\n- Opcode: 0x%02x%s%s\n", op.Name, immediateMarkdown(op), op.Opcode, ws, opextra)
- if op.Args == nil {
- fmt.Fprintf(out, "- Pops: _None_\n")
- } else if len(op.Args) == 1 {
- fmt.Fprintf(out, "- Pops: *... stack*, %s\n", op.Args[0].String())
- } else {
- fmt.Fprintf(out, "- Pops: *... stack*, {%s A}", op.Args[0].String())
- for i, v := range op.Args[1:] {
- fmt.Fprintf(out, ", {%s %c}", v.String(), rune(int('B')+i))
+
+ out += "..."
+ for i, v := range op.Args {
+ out += fmt.Sprintf(", %c", rune(int('A')+i))
+ if v.Typed() {
+ out += fmt.Sprintf(": %s", v)
}
- out.Write([]byte("\n"))
}
+ out += " → ..."
- if op.Returns == nil {
- fmt.Fprintf(out, "- Pushes: _None_\n")
- } else {
- if len(op.Returns) == 1 {
- fmt.Fprintf(out, "- Pushes: %s", op.Returns[0].String())
- } else {
- fmt.Fprintf(out, "- Pushes: *... stack*, %s", op.Returns[0].String())
- for _, rt := range op.Returns[1:] {
- fmt.Fprintf(out, ", %s", rt.String())
+ for i, rt := range op.Returns {
+ out += ", "
+ if len(op.Returns) > 1 {
+ start := int('X')
+ if len(op.Returns) > 3 {
+ start = int('Z') + 1 - len(op.Returns)
}
+ out += fmt.Sprintf("%c: ", rune(start+i))
}
- fmt.Fprintf(out, "\n")
+ out += rt.String()
}
+ return out + "\n"
+}
+
+func opToMarkdown(out io.Writer, op *logic.OpSpec) (err error) {
+ ws := ""
+ opextra := logic.OpImmediateNote(op.Name)
+ if opextra != "" {
+ ws = " "
+ }
+ stackEffects := stackMarkdown(op)
+ fmt.Fprintf(out, "\n## %s%s\n\n- Opcode: 0x%02x%s%s\n%s",
+ op.Name, immediateMarkdown(op), op.Opcode, ws, opextra, stackEffects)
fmt.Fprintf(out, "- %s\n", logic.OpDoc(op.Name))
// if cost changed with versions print all of them
costs := logic.OpAllCosts(op.Name)
@@ -170,12 +206,12 @@ func opToMarkdown(out io.Writer, op *logic.OpSpec) (err error) {
fmt.Fprintf(out, "- **Cost**:\n")
for _, cost := range costs {
if cost.From == cost.To {
- fmt.Fprintf(out, " - %d (LogicSigVersion = %d)\n", cost.Cost, cost.To)
+ fmt.Fprintf(out, " - %d (v%d)\n", cost.Cost, cost.To)
} else {
if cost.To < logic.LogicVersion {
- fmt.Fprintf(out, " - %d (%d <= LogicSigVersion <= %d)\n", cost.Cost, cost.From, cost.To)
+ fmt.Fprintf(out, " - %d (v%d - v%d)\n", cost.Cost, cost.From, cost.To)
} else {
- fmt.Fprintf(out, " - %d (LogicSigVersion >= %d)\n", cost.Cost, cost.From)
+ fmt.Fprintf(out, " - %d (since v%d)\n", cost.Cost, cost.From)
}
}
}
@@ -186,7 +222,7 @@ func opToMarkdown(out io.Writer, op *logic.OpSpec) (err error) {
}
}
if op.Version > 1 {
- fmt.Fprintf(out, "- LogicSigVersion >= %d\n", op.Version)
+ fmt.Fprintf(out, "- Availability: v%d\n", op.Version)
}
if !op.Modes.Any() {
fmt.Fprintf(out, "- Mode: %s\n", op.Modes.String())
@@ -250,28 +286,6 @@ type LanguageSpec struct {
Ops []OpRecord
}
-func argEnum(name string) []string {
- if name == "txn" || name == "gtxn" || name == "gtxns" {
- return logic.TxnFieldNames
- }
- if name == "global" {
- return logic.GlobalFieldNames
- }
- if name == "txna" || name == "gtxna" || name == "gtxnsa" || name == "txnas" || name == "gtxnas" || name == "gtxnsas" {
- return logic.TxnaFieldNames
- }
- if name == "asset_holding_get" {
- return logic.AssetHoldingFieldNames
- }
- if name == "asset_params_get" {
- return logic.AssetParamsFieldNames
- }
- if name == "app_params_get" {
- return logic.AppParamsFieldNames
- }
- return nil
-}
-
func typeString(types []logic.StackType) string {
out := make([]byte, len(types))
for i, t := range types {
@@ -294,27 +308,32 @@ func typeString(types []logic.StackType) string {
return string(out)
}
-func argEnumTypes(name string) string {
- if name == "txn" || name == "gtxn" || name == "gtxns" {
- return typeString(logic.TxnFieldTypes)
- }
- if name == "global" {
- return typeString(logic.GlobalFieldTypes)
- }
- if name == "txna" || name == "gtxna" || name == "gtxnsa" || name == "txnas" || name == "gtxnas" || name == "gtxnsas" {
- return typeString(logic.TxnaFieldTypes)
- }
- if name == "asset_holding_get" {
- return typeString(logic.AssetHoldingFieldTypes)
- }
- if name == "asset_params_get" {
- return typeString(logic.AssetParamsFieldTypes)
- }
- if name == "app_params_get" {
- return typeString(logic.AppParamsFieldTypes)
+func fieldsAndTypes(names []string, specs speccer) ([]string, string) {
+ types := make([]logic.StackType, len(names))
+ for i, name := range names {
+ types[i] = specs.SpecByName(name).Type()
}
+ return names, typeString(types)
+}
- return ""
+func argEnums(name string) (names []string, types string) {
+ switch name {
+ case "txn", "gtxn", "gtxns", "itxn", "gitxn", "itxn_field":
+ return fieldsAndTypes(logic.TxnFieldNames, logic.TxnFieldSpecByName)
+ case "global":
+ return
+ case "txna", "gtxna", "gtxnsa", "txnas", "gtxnas", "gtxnsas", "itxna", "gitxna":
+ // Map is the whole txn field spec map. That's fine, we only lookup the given names.
+ return fieldsAndTypes(logic.TxnaFieldNames(), logic.TxnFieldSpecByName)
+ case "asset_holding_get":
+ return fieldsAndTypes(logic.AssetHoldingFieldNames, logic.AssetHoldingFieldSpecByName)
+ case "asset_params_get":
+ return fieldsAndTypes(logic.AssetParamsFieldNames, logic.AssetParamsFieldSpecByName)
+ case "app_params_get":
+ return fieldsAndTypes(logic.AppParamsFieldNames, logic.AppParamsFieldSpecByName)
+ default:
+ return nil, ""
+ }
}
func buildLanguageSpec(opGroups map[string][]string) *LanguageSpec {
@@ -327,8 +346,7 @@ func buildLanguageSpec(opGroups map[string][]string) *LanguageSpec {
records[i].Returns = typeString(spec.Returns)
records[i].Cost = spec.Details.Cost
records[i].Size = spec.Details.Size
- records[i].ArgEnum = argEnum(spec.Name)
- records[i].ArgEnumTypes = argEnumTypes(spec.Name)
+ records[i].ArgEnum, records[i].ArgEnumTypes = argEnums(spec.Name)
records[i].Doc = logic.OpDoc(spec.Name)
records[i].DocExtra = logic.OpDocExtra(spec.Name)
records[i].ImmediateNote = logic.OpImmediateNote(spec.Name)
@@ -361,25 +379,29 @@ func main() {
constants.Close()
txnfields, _ := os.Create("txn_fields.md")
- fieldTableMarkdown(txnfields, logic.TxnFieldNames, logic.TxnFieldTypes, logic.TxnFieldDocs())
+ fieldSpecsMarkdown(txnfields, logic.TxnFieldNames, logic.TxnFieldSpecByName)
txnfields.Close()
globalfields, _ := os.Create("global_fields.md")
- fieldTableMarkdown(globalfields, logic.GlobalFieldNames, logic.GlobalFieldTypes, logic.GlobalFieldDocs())
+ fieldSpecsMarkdown(globalfields, logic.GlobalFieldNames, logic.GlobalFieldSpecByName)
globalfields.Close()
assetholding, _ := os.Create("asset_holding_fields.md")
- fieldTableMarkdown(assetholding, logic.AssetHoldingFieldNames, logic.AssetHoldingFieldTypes, logic.AssetHoldingFieldDocs)
+ fieldSpecsMarkdown(assetholding, logic.AssetHoldingFieldNames, logic.AssetHoldingFieldSpecByName)
assetholding.Close()
assetparams, _ := os.Create("asset_params_fields.md")
- fieldTableMarkdown(assetparams, logic.AssetParamsFieldNames, logic.AssetParamsFieldTypes, logic.AssetParamsFieldDocs())
+ fieldSpecsMarkdown(assetparams, logic.AssetParamsFieldNames, logic.AssetParamsFieldSpecByName)
assetparams.Close()
appparams, _ := os.Create("app_params_fields.md")
- fieldTableMarkdown(appparams, logic.AppParamsFieldNames, logic.AppParamsFieldTypes, logic.AppParamsFieldDocs())
+ fieldSpecsMarkdown(appparams, logic.AppParamsFieldNames, logic.AppParamsFieldSpecByName)
appparams.Close()
+ acctparams, _ := os.Create("acct_params_fields.md")
+ fieldSpecsMarkdown(acctparams, logic.AcctParamsFieldNames, logic.AcctParamsFieldSpecByName)
+ acctparams.Close()
+
langspecjs, _ := os.Create("langspec.json")
enc := json.NewEncoder(langspecjs)
enc.Encode(buildLanguageSpec(opGroups))