Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
parity
Mirrored projects
ink
Commits
45c3f21c
Unverified
Commit
45c3f21c
authored
Mar 19, 2019
by
Robin Freyler
Browse files
[lang] Add initial implementation of JSON api generation
parent
1ef375ee
Changes
4
Hide whitespace changes
Inline
Side-by-side
lang/Cargo.toml
View file @
45c3f21c
...
...
@@ -28,6 +28,8 @@ proc-macro2 = "0.4"
heck
=
"0.3"
itertools
=
"0.7"
either
=
"1.5"
serde
=
{
version
=
"1.0.89"
,
features
=
["derive"]
}
serde_json
=
"1.0.39"
[lib]
name
=
"pdsl_lang"
...
...
lang/src/api.rs
0 → 100644
View file @
45c3f21c
use
crate
::{
ast
,
errors
::
Result
,
hir
,
ident_ext
::
IdentExt
,
};
use
serde
::{
Deserialize
,
Serialize
,
};
use
serde_json
::{
json
,
Value
as
JsonValue
,
};
/// Describes a message parameter or return type.
#[derive(Debug,
PartialEq,
Eq,
Deserialize,
Serialize)]
pub
enum
TypeDescription
{
/// The `bool` primitive type.
Bool
,
/// The `u8` primitive unsigned integer.
U8
,
/// The `u16` primitive unsigned integer.
U16
,
/// The `u32` primitive unsigned integer.
U32
,
/// The `u64` primitive unsigned integer.
U64
,
/// The `u128` primitive unsigned integer.
U128
,
/// The `i8` primitive signed integer.
I8
,
/// The `i16` primitive signed integer.
I16
,
/// The `i32` primitive signed integer.
I32
,
/// The `i64` primitive signed integer.
I64
,
/// The `i128` primitive signed integer.
I128
,
/// The SRML address type.
Address
,
/// The SRML balance type.
Balance
,
/// Custom type.
Custom
(
String
),
}
impl
From
<&
syn
::
Type
>
for
TypeDescription
{
fn
from
(
ty
:
&
syn
::
Type
)
->
Self
{
use
quote
::
ToTokens
;
match
ty
.into_token_stream
()
.to_string
()
.as_str
()
{
"bool"
=>
TypeDescription
::
Bool
,
"u8"
=>
TypeDescription
::
U8
,
"u16"
=>
TypeDescription
::
U16
,
"u32"
=>
TypeDescription
::
U32
,
"u64"
=>
TypeDescription
::
U64
,
"u128"
=>
TypeDescription
::
U128
,
"i8"
=>
TypeDescription
::
I8
,
"i16"
=>
TypeDescription
::
I16
,
"i32"
=>
TypeDescription
::
I32
,
"i64"
=>
TypeDescription
::
I64
,
"i128"
=>
TypeDescription
::
I128
,
"Address"
=>
TypeDescription
::
Address
,
"Balance"
=>
TypeDescription
::
Balance
,
custom
=>
TypeDescription
::
Custom
(
custom
.to_owned
()),
}
}
}
/// Describes a pair of parameter name and type.
#[derive(Debug,
PartialEq,
Eq,
Deserialize,
Serialize)]
pub
struct
ParamDescription
{
/// The name of the parameter.
name
:
String
,
/// The type of the parameter.
ty
:
TypeDescription
,
}
impl
From
<&
syn
::
ArgCaptured
>
for
ParamDescription
{
fn
from
(
arg
:
&
syn
::
ArgCaptured
)
->
Self
{
let
name
=
match
&
arg
.pat
{
syn
::
Pat
::
Ident
(
ident
)
=>
ident
.ident
.to_owned_string
(),
_
=>
panic!
(
"cannot handle non-ident function arguments"
),
};
Self
{
name
,
ty
:
TypeDescription
::
from
(
&
arg
.ty
),
}
}
}
/// Describes the deploy handler of a contract.
#[derive(Debug,
PartialEq,
Eq,
Deserialize,
Serialize)]
pub
struct
DeployDescription
{
/// The parameters of the deploy handler.
params
:
Vec
<
ParamDescription
>
,
}
impl
From
<&
hir
::
DeployHandler
>
for
DeployDescription
{
fn
from
(
deploy_handler
:
&
hir
::
DeployHandler
)
->
Self
{
Self
{
params
:
{
deploy_handler
.decl
.inputs
.iter
()
.filter_map
(|
arg
|
{
match
arg
{
ast
::
FnArg
::
Captured
(
captured
)
=>
{
Some
(
ParamDescription
::
from
(
captured
))
}
_
=>
None
,
}
})
.collect
::
<
Vec
<
_
>>
()
},
}
}
}
/// Describes the return type of a contract message.
#[derive(Debug,
PartialEq,
Eq,
Deserialize,
Serialize)]
pub
struct
ReturnTypeDescription
{
/// The optional return type.
ret_ty
:
Option
<
TypeDescription
>
,
}
impl
ReturnTypeDescription
{
/// Creates a new return type description from the given optional type.
pub
fn
new
<
T
>
(
opt_type
:
T
)
->
Self
where
T
:
Into
<
Option
<
TypeDescription
>>
,
{
Self
{
ret_ty
:
opt_type
.into
(),
}
}
}
impl
From
<&
syn
::
ReturnType
>
for
ReturnTypeDescription
{
fn
from
(
ret_ty
:
&
syn
::
ReturnType
)
->
Self
{
match
ret_ty
{
syn
::
ReturnType
::
Default
=>
ReturnTypeDescription
::
new
(
None
),
syn
::
ReturnType
::
Type
(
_
,
ty
)
=>
{
ReturnTypeDescription
::
new
(
Some
(
TypeDescription
::
from
(
&**
ty
)))
}
}
}
}
/// Describes a contract message.
#[derive(Debug,
PartialEq,
Eq,
Deserialize,
Serialize)]
pub
struct
MessageDescription
{
/// The name of the message.
name
:
String
,
/// The selector hash of the message.
selector
:
u64
,
/// If the message is allowed to mutate the contract state.
mutates
:
bool
,
/// The parameters of the message.
params
:
Vec
<
ParamDescription
>
,
/// The return type of the message.
ret_ty
:
ReturnTypeDescription
,
}
impl
From
<&
hir
::
Message
>
for
MessageDescription
{
fn
from
(
message
:
&
hir
::
Message
)
->
Self
{
Self
{
name
:
message
.sig.ident
.to_owned_string
(),
selector
:
message
.selector
()
.into
(),
mutates
:
message
.is_mut
(),
params
:
{
message
.sig
.decl
.inputs
.iter
()
.filter_map
(|
arg
|
{
match
arg
{
ast
::
FnArg
::
Captured
(
captured
)
=>
{
Some
(
ParamDescription
::
from
(
captured
))
}
_
=>
None
,
}
})
.collect
::
<
Vec
<
_
>>
()
},
ret_ty
:
ReturnTypeDescription
::
from
(
&
message
.sig.decl.output
),
}
}
}
/// Describes a contract.
#[derive(Debug,
PartialEq,
Eq,
Deserialize,
Serialize)]
pub
struct
ContractDescription
{
/// The name of the contract.
name
:
String
,
/// The deploy handler of the contract.
deploy
:
DeployDescription
,
/// The external messages of the contract.
messages
:
Vec
<
MessageDescription
>
,
}
impl
ContractDescription
{
/// Returns the name of the contract.
pub
fn
name
(
&
self
)
->
&
str
{
&
self
.name
}
}
impl
From
<&
hir
::
Contract
>
for
ContractDescription
{
fn
from
(
contract
:
&
hir
::
Contract
)
->
Self
{
ContractDescription
{
name
:
contract
.name
.to_owned_string
(),
deploy
:
DeployDescription
::
from
(
&
contract
.on_deploy
),
messages
:
{
contract
.messages
.iter
()
.map
(
MessageDescription
::
from
)
.collect
::
<
Vec
<
_
>>
()
},
}
}
}
pub
fn
generate_api_description
(
contract
:
&
hir
::
Contract
)
{
let
description
=
ContractDescription
::
from
(
contract
);
let
contents
=
serde_json
::
to_string
(
&
description
)
.unwrap
();
let
mut
path_buf
=
String
::
from
(
"target/"
);
path_buf
.push_str
(
description
.name
());
path_buf
.push_str
(
".json"
);
std
::
fs
::
write
(
path_buf
,
contents
);
}
lang/src/hir.rs
View file @
45c3f21c
...
...
@@ -373,6 +373,11 @@ impl Message {
_
=>
panic!
(),
}
}
/// Returns the message selector for this message.
pub
fn
selector
(
&
self
)
->
u32
{
0
}
}
impl
From
<&
ast
::
ItemImplMethod
>
for
Message
{
...
...
lang/src/lib.rs
View file @
45c3f21c
...
...
@@ -31,6 +31,7 @@ pub fn contract(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
#[macro_use]
mod
errors
;
mod
api
;
mod
ast
;
mod
gen
;
mod
hir
;
...
...
@@ -60,6 +61,7 @@ pub(crate) fn contract_gen_impl2(
)
->
Result
<
proc_macro2
::
TokenStream
>
{
let
ast_contract
=
parser
::
parse_contract
(
input
.clone
())
?
;
let
hir_contract
=
hir
::
Contract
::
from_ast
(
&
ast_contract
)
?
;
api
::
generate_api_description
(
&
hir_contract
);
// gen::gir::generate(&hir_program)?;
let
tokens
=
gen
::
codegen
(
&
hir_contract
);
Ok
(
tokens
.into
())
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new 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