Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
N
neoppod
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Levin Zimmermann
neoppod
Commits
fd40d0b4
Commit
fd40d0b4
authored
Jan 25, 2017
by
Kirill Smelkov
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
.
parent
3208e747
Changes
1
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
25 additions
and
58 deletions
+25
-58
t/neo/protogen.go
t/neo/protogen.go
+25
-58
No files found.
t/neo/protogen.go
View file @
fd40d0b4
...
@@ -10,6 +10,8 @@
...
@@ -10,6 +10,8 @@
//
//
// See COPYING file for full licensing terms.
// See COPYING file for full licensing terms.
// +build ignore
/*
/*
NEO. Protocol definition. Code generator
NEO. Protocol definition. Code generator
...
@@ -30,8 +32,8 @@ maps, ...).
...
@@ -30,8 +32,8 @@ maps, ...).
Top-level generation driver is in generateCodecCode(). It accepts type
Top-level generation driver is in generateCodecCode(). It accepts type
specification and something that performs actual leaf-nodes code generation
specification and something that performs actual leaf-nodes code generation
(Code
cCodeGen interface).
There are 3 particular codegenerators implemented -
(Code
Generator interface).
There are 3 particular codegenerators implemented -
- sizer, encoder & decoder - to generate each of the needed method functions.
- sizer, encoder & decoder - to generate each of the needed method functions.
XXX naming
The structure of whole process is very similar to what would be happening at
The structure of whole process is very similar to what would be happening at
runtime if marshalling was reflect based, but statically with go/types we don't
runtime if marshalling was reflect based, but statically with go/types we don't
...
@@ -45,8 +47,6 @@ NOTE we do no try to emit very clever code - for cases where compiler
...
@@ -45,8 +47,6 @@ NOTE we do no try to emit very clever code - for cases where compiler
can do a good job the work is delegated to it.
can do a good job the work is delegated to it.
*/
*/
// +build ignore
package
main
package
main
import
(
import
(
...
@@ -86,7 +86,7 @@ func main() {
...
@@ -86,7 +86,7 @@ func main() {
log
.
SetFlags
(
0
)
log
.
SetFlags
(
0
)
// go through proto.go and
collect packets type definitions
// go through proto.go and
AST'ify & typecheck it
var
fv
[]
*
ast
.
File
var
fv
[]
*
ast
.
File
for
_
,
src
:=
range
[]
string
{
"proto.go"
,
"neo.go"
}
{
for
_
,
src
:=
range
[]
string
{
"proto.go"
,
"neo.go"
}
{
f
,
err
:=
parser
.
ParseFile
(
fset
,
src
,
nil
,
0
)
f
,
err
:=
parser
.
ParseFile
(
fset
,
src
,
nil
,
0
)
...
@@ -142,11 +142,6 @@ import (
...
@@ -142,11 +142,6 @@ import (
continue
continue
case
*
ast
.
StructType
:
case
*
ast
.
StructType
:
//fmt.Printf("\n%s:\n", typename)
//fmt.Println(typespec)
//ast.Print(fset, typespec)
//continue
fmt
.
Fprintf
(
&
buf
,
"// %d. %s
\n\n
"
,
pktCode
,
typename
)
fmt
.
Fprintf
(
&
buf
,
"// %d. %s
\n\n
"
,
pktCode
,
typename
)
buf
.
WriteString
(
generateCodecCode
(
typespec
,
&
sizer
{}))
buf
.
WriteString
(
generateCodecCode
(
typespec
,
&
sizer
{}))
...
@@ -179,8 +174,8 @@ type basicCodec struct {
...
@@ -179,8 +174,8 @@ type basicCodec struct {
}
}
var
basicTypes
=
map
[
types
.
BasicKind
]
basicCodec
{
var
basicTypes
=
map
[
types
.
BasicKind
]
basicCodec
{
// decode: %v will be `data[n:]` (and made sure data has more enough bytes to read)
// encode: %v %v will be `data[n:]`, value
// encode: %v %v will be `data[n:]`, value
// decode: %v will be `data[n:]` (and already made sure data has more enough bytes to read)
types
.
Bool
:
{
1
,
"(%v)[0] = bool2byte(%v)"
,
"byte2bool((%v)[0])"
},
types
.
Bool
:
{
1
,
"(%v)[0] = bool2byte(%v)"
,
"byte2bool((%v)[0])"
},
types
.
Int8
:
{
1
,
"(%v)[0] = uint8(%v)"
,
"int8((%v)[0])"
},
types
.
Int8
:
{
1
,
"(%v)[0] = uint8(%v)"
,
"int8((%v)[0])"
},
types
.
Int16
:
{
2
,
"binary.BigEndian.PutUint16(%v, uint16(%v))"
,
"int16(binary.BigEndian.Uint16(%v))"
},
types
.
Int16
:
{
2
,
"binary.BigEndian.PutUint16(%v, uint16(%v))"
,
"int16(binary.BigEndian.Uint16(%v))"
},
...
@@ -234,7 +229,7 @@ func typeSizeFixed1(typ types.Type) bool {
...
@@ -234,7 +229,7 @@ func typeSizeFixed1(typ types.Type) bool {
}
}
// Buffer + bell & whistles
//
bytes.
Buffer + bell & whistles
type
Buffer
struct
{
type
Buffer
struct
{
bytes
.
Buffer
bytes
.
Buffer
}
}
...
@@ -243,9 +238,8 @@ func (b *Buffer) emit(format string, a ...interface{}) {
...
@@ -243,9 +238,8 @@ func (b *Buffer) emit(format string, a ...interface{}) {
fmt
.
Fprintf
(
b
,
format
+
"
\n
"
,
a
...
)
fmt
.
Fprintf
(
b
,
format
+
"
\n
"
,
a
...
)
}
}
// interface of codegenerator for sizer/coder/decoder
// interface of a codegenerator (for sizer/coder/decoder XXX naming)
// XXX naming?
type
CodeGenerator
interface
{
type
CodecCodeGen
interface
{
// tell codegen it should generate code for top-level function
// tell codegen it should generate code for top-level function
setFunc
(
recvName
,
typeName
string
,
typ
types
.
Type
)
setFunc
(
recvName
,
typeName
string
,
typ
types
.
Type
)
...
@@ -259,19 +253,15 @@ type CodecCodeGen interface {
...
@@ -259,19 +253,15 @@ type CodecCodeGen interface {
genMap
(
path
string
,
typ
*
types
.
Map
,
obj
types
.
Object
)
genMap
(
path
string
,
typ
*
types
.
Map
,
obj
types
.
Object
)
// particular case of slice or array with 1-byte elem
// particular case of slice or array with 1-byte elem
//
// NOTE this particular case is kept separate because for 1-byte
// elements there are no byteordering issues so data can be directly
// either accessed or copied.
genSlice1
(
path
string
,
typ
types
.
Type
)
genSlice1
(
path
string
,
typ
types
.
Type
)
genArray1
(
path
string
,
typ
*
types
.
Array
)
genArray1
(
path
string
,
typ
*
types
.
Array
)
// get generated code.
// get generated code.
// for top-level functions this is whole function including return and closing }
// for not function this is generated code needed for resultExpr()
generatedCode
()
string
generatedCode
()
string
/*
// get result expression
// this is result of computations for not top-level code XXX
resultExpr() string
*/
}
}
// common part of codegenerators
// common part of codegenerators
...
@@ -381,32 +371,15 @@ type decoder struct {
...
@@ -381,32 +371,15 @@ type decoder struct {
commonCoder
commonCoder
}
}
var
_
CodecCodeGen
=
(
*
sizer
)(
nil
)
var
_
CodeGenerator
=
(
*
sizer
)(
nil
)
var
_
CodecCodeGen
=
(
*
encoder
)(
nil
)
var
_
CodeGenerator
=
(
*
encoder
)(
nil
)
var
_
CodecCodeGen
=
(
*
decoder
)(
nil
)
var
_
CodeGenerator
=
(
*
decoder
)(
nil
)
/*
// create new sizer for subsize calculation (e.g. inside loop)
func (s *sizer) subSizer() *sizer {
return &sizer{commonCoder: commonCoder{varN: s.varN + 1}}
}
*/
func
(
s
*
sizer
)
resultExpr
()
string
{
size
:=
s
.
size
.
String
()
if
s
.
varUsed
[
"size"
]
{
size
+=
" + "
+
s
.
var__
(
"size"
)
}
return
size
}
func
(
s
*
sizer
)
generatedCode
()
string
{
func
(
s
*
sizer
)
generatedCode
()
string
{
code
:=
Buffer
{}
code
:=
Buffer
{}
// prologue
// prologue
//if s.recvName != "" { XXX remove
code
.
emit
(
"func (%s *%s) NEOEncodedLen() int {"
,
s
.
recvName
,
s
.
typeName
)
code
.
emit
(
"func (%s *%s) NEOEncodedLen() int {"
,
s
.
recvName
,
s
.
typeName
)
//}
if
s
.
varUsed
[
"size"
]
{
if
s
.
varUsed
[
"size"
]
{
code
.
emit
(
"var %s int"
,
s
.
var__
(
"size"
))
code
.
emit
(
"var %s int"
,
s
.
var__
(
"size"
))
}
}
...
@@ -414,10 +387,12 @@ func (s *sizer) generatedCode() string {
...
@@ -414,10 +387,12 @@ func (s *sizer) generatedCode() string {
code
.
Write
(
s
.
Bytes
())
// XXX -> s.buf.Bytes() ?
code
.
Write
(
s
.
Bytes
())
// XXX -> s.buf.Bytes() ?
// epilogue
// epilogue
//if s.recvName != "" { XXX remove
size
:=
s
.
size
.
String
()
code
.
emit
(
"return %v"
,
s
.
resultExpr
())
if
s
.
varUsed
[
"size"
]
{
size
+=
" + "
+
s
.
var__
(
"size"
)
}
code
.
emit
(
"return %v"
,
size
)
code
.
emit
(
"}
\n
"
)
code
.
emit
(
"}
\n
"
)
//}
return
code
.
String
()
return
code
.
String
()
}
}
...
@@ -645,14 +620,6 @@ func (s *sizer) genSlice(path string, typ *types.Slice, obj types.Object) {
...
@@ -645,14 +620,6 @@ func (s *sizer) genSlice(path string, typ *types.Slice, obj types.Object) {
curSize
.
AddExpr
(
"len(%v) * %v"
,
path
,
s
.
size
.
num
)
curSize
.
AddExpr
(
"len(%v) * %v"
,
path
,
s
.
size
.
num
)
}
}
s
.
size
=
curSize
s
.
size
=
curSize
/*
sloop := s.subSizer()
codegenType("(*a)", typ.Elem(), obj, sloop)
s.emit(sloop.generatedCode())
s.emit("%v += %v", s.var_("size"), sloop.resultExpr())
s.emit("}")
*/
}
}
// TODO optimize for []byte
// TODO optimize for []byte
...
@@ -843,7 +810,7 @@ func (d *decoder) genMap(assignto string, typ *types.Map, obj types.Object) {
...
@@ -843,7 +810,7 @@ func (d *decoder) genMap(assignto string, typ *types.Map, obj types.Object) {
// obj is object that uses this type in source program (so in case of an error
// obj is object that uses this type in source program (so in case of an error
// we can point to source location for where it happenned)
// we can point to source location for where it happenned)
func
codegenType
(
path
string
,
typ
types
.
Type
,
obj
types
.
Object
,
codegen
Code
cCodeGen
)
{
func
codegenType
(
path
string
,
typ
types
.
Type
,
obj
types
.
Object
,
codegen
Code
Generator
)
{
switch
u
:=
typ
.
Underlying
()
.
(
type
)
{
switch
u
:=
typ
.
Underlying
()
.
(
type
)
{
case
*
types
.
Basic
:
case
*
types
.
Basic
:
if
u
.
Kind
()
==
types
.
String
{
if
u
.
Kind
()
==
types
.
String
{
...
@@ -895,7 +862,7 @@ func codegenType(path string, typ types.Type, obj types.Object, codegen CodecCod
...
@@ -895,7 +862,7 @@ func codegenType(path string, typ types.Type, obj types.Object, codegen CodecCod
// generate encoder/decode funcs for a type declaration typespec
// generate encoder/decode funcs for a type declaration typespec
// XXX name? -> genMethCode ? generateMethodCode ?
// XXX name? -> genMethCode ? generateMethodCode ?
func
generateCodecCode
(
typespec
*
ast
.
TypeSpec
,
codegen
Code
cCodeGen
)
string
{
func
generateCodecCode
(
typespec
*
ast
.
TypeSpec
,
codegen
Code
Generator
)
string
{
// type & object which refers to this type
// type & object which refers to this type
typ
:=
info
.
Types
[
typespec
.
Type
]
.
Type
typ
:=
info
.
Types
[
typespec
.
Type
]
.
Type
obj
:=
info
.
Defs
[
typespec
.
Name
]
obj
:=
info
.
Defs
[
typespec
.
Name
]
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment