@@ -8,6 +8,7 @@ target
|
||||
|
||||
# MSVC Windows builds of rustc generate these, which store debugging information
|
||||
*.pdb
|
||||
*.exe
|
||||
|
||||
# Generated by cargo mutants
|
||||
# Contains mutation testing data
|
||||
|
||||
+32
-11
@@ -17,10 +17,22 @@ pub enum TypePostfix {
|
||||
RefMut,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize)]
|
||||
pub enum Attribute {
|
||||
/// #[test]
|
||||
Path(Path),
|
||||
|
||||
/// #[name = "value"]
|
||||
NameValue { path: Path, value: Literal },
|
||||
|
||||
/// #[derive(Clone, Copy)]
|
||||
List { path: Path, items: Vec<Attribute> },
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize)]
|
||||
pub enum TypeExprKind {
|
||||
Path(StaticPath),
|
||||
PathParams(StaticPath, Vec<TypeExpr>),
|
||||
Path(Path),
|
||||
PathParams(Path, Vec<TypeExpr>),
|
||||
Tuple(Vec<TypeExpr>),
|
||||
}
|
||||
|
||||
@@ -28,7 +40,7 @@ pub enum TypeExprKind {
|
||||
pub struct TypeExpr(pub TypeExprKind, pub Vec<TypePostfix>);
|
||||
|
||||
#[derive(Debug, Clone, Serialize)]
|
||||
pub struct StaticPath(pub Vec<String>);
|
||||
pub struct Path(pub Vec<String>);
|
||||
|
||||
#[derive(Debug, Clone, Serialize)]
|
||||
pub enum BinaryOp {
|
||||
@@ -46,8 +58,12 @@ pub enum BinaryOp {
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize)]
|
||||
pub enum TopLevel {
|
||||
Include(StaticPath),
|
||||
pub struct TopLevel(pub TopLevelKind, pub Vec<Attribute>);
|
||||
|
||||
#[derive(Debug, Clone, Serialize)]
|
||||
pub enum TopLevelKind {
|
||||
ModAttribute,
|
||||
Include(Path),
|
||||
StructDecl {
|
||||
export: bool,
|
||||
name: String,
|
||||
@@ -137,15 +153,20 @@ pub struct ForStmt {
|
||||
|
||||
#[derive(Debug, Clone, Serialize)]
|
||||
pub enum Expression {
|
||||
Path(StaticPath),
|
||||
IntLiteral(i64),
|
||||
FloatLiteral(f64),
|
||||
BoolLiteral(bool),
|
||||
StringLiteral(String),
|
||||
TupleLiteral(Vec<Expression>),
|
||||
Literal(Literal),
|
||||
Path(Path),
|
||||
Fix {
|
||||
initial: Box<Expression>,
|
||||
prefixes: Vec<Prefix>,
|
||||
postfixes: Vec<Postfix>,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize)]
|
||||
pub enum Literal {
|
||||
String(String),
|
||||
Int(i64),
|
||||
Float(f64),
|
||||
Bool(bool),
|
||||
Tuple(Vec<Expression>),
|
||||
}
|
||||
|
||||
+22
-4
@@ -19,7 +19,25 @@ var_decl = { type_expr ~ mutable? ~ identifier }
|
||||
|
||||
// ================= TOP LEVEL =================
|
||||
|
||||
top_level = _{ import | function_decl | struct_decl }
|
||||
attribute = {
|
||||
"#" ~ "[" ~ meta ~ "]"
|
||||
}
|
||||
|
||||
mod_attribute = {
|
||||
"#" ~ "!" ~ "[" ~ meta ~ "]"
|
||||
}
|
||||
|
||||
meta = {
|
||||
static_path ~ ("=" ~ primary | "(" ~ meta_list? ~ ")")?
|
||||
}
|
||||
|
||||
meta_list = {
|
||||
meta ~ ("," ~ meta)* ~ ","?
|
||||
}
|
||||
|
||||
attributes = { attribute* }
|
||||
|
||||
top_level = { (attributes ~ (import | function_decl | struct_decl)) | mod_attribute }
|
||||
|
||||
import = { sharp ~ "include" ~ "<" ~ static_path ~ ">" }
|
||||
|
||||
@@ -90,8 +108,8 @@ macro_inner_v = {
|
||||
tuple = { "(" ~ (expr ~ ("," ~ expr)*)? ~ ")" }
|
||||
|
||||
primary = {
|
||||
integer
|
||||
| float
|
||||
float
|
||||
| integer
|
||||
| boolean
|
||||
| string_lit
|
||||
| static_path
|
||||
@@ -110,7 +128,7 @@ postfix = {
|
||||
field_px = { "." ~ identifier }
|
||||
call_px = { "(" ~ (expr ~ ("," ~ expr)*)? ~ ")" }
|
||||
macro_call_px = { "!" ~ "(" ~ macro_inner_v* ~ ")" }
|
||||
struct_px = { "{" ~ (struct_field_decl ~ ("," ~ struct_field_decl)*)? ~ "}" }
|
||||
struct_px = { "{" ~ (struct_field_decl ~ ("," ~ struct_field_decl)*)? ~ ","? ~ "}" }
|
||||
index_px = { "[" ~ expr ~ "]" }
|
||||
binary_px = { bin_op ~ expr }
|
||||
bin_op = { "+" | "-" | "*" | "/" | "%" | "==" | "!=" | "<" | ">" | "<=" | ">=" }
|
||||
|
||||
+121
-23
@@ -18,8 +18,8 @@ pub fn parse(source: &str) -> Result<Vec<TopLevel>, ParseError> {
|
||||
let mut statements = vec![];
|
||||
|
||||
for pair in pairs.next().unwrap().into_inner() {
|
||||
if let Ok(stmt) = TopLevel::try_from(pair) {
|
||||
statements.push(stmt);
|
||||
if pair.as_rule() != Rule::EOI {
|
||||
statements.push(TopLevel::from(pair));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -67,7 +67,7 @@ impl From<pest::iterators::Pair<'_, Rule>> for TypeExprKind {
|
||||
match rule {
|
||||
Rule::tuple_type => TypeExprKind::Tuple(inner.map(TypeExpr::from).collect()),
|
||||
Rule::path_type => {
|
||||
let path = StaticPath::from(inner.next().unwrap());
|
||||
let path = Path::from(inner.next().unwrap());
|
||||
let params = inner.map(TypeExpr::from).collect::<Vec<_>>();
|
||||
|
||||
if params.len() == 0 {
|
||||
@@ -81,12 +81,10 @@ impl From<pest::iterators::Pair<'_, Rule>> for TypeExprKind {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<pest::iterators::Pair<'_, Rule>> for StaticPath {
|
||||
impl From<pest::iterators::Pair<'_, Rule>> for Path {
|
||||
fn from(pair: pest::iterators::Pair<'_, Rule>) -> Self {
|
||||
match pair.as_rule() {
|
||||
Rule::static_path => {
|
||||
StaticPath(pair.into_inner().map(|i| i.as_str().to_string()).collect())
|
||||
}
|
||||
Rule::static_path => Path(pair.into_inner().map(|i| i.as_str().to_string()).collect()),
|
||||
_ => unimplemented!("{pair:#?}"),
|
||||
}
|
||||
}
|
||||
@@ -120,14 +118,91 @@ impl From<pest::iterators::Pair<'_, Rule>> for ParamList {
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<pest::iterators::Pair<'_, Rule>> for TopLevel {
|
||||
type Error = ();
|
||||
fn try_from(pair: pest::iterators::Pair<Rule>) -> Result<Self, ()> {
|
||||
impl From<pest::iterators::Pair<'_, Rule>> for Attribute {
|
||||
fn from(pair: pest::iterators::Pair<'_, Rule>) -> Self {
|
||||
match pair.as_rule() {
|
||||
Rule::attribute => {
|
||||
// unwrap #[ ... ]
|
||||
Attribute::from(pair.into_inner().next().unwrap())
|
||||
}
|
||||
|
||||
Rule::meta => {
|
||||
let mut inner = pair.into_inner();
|
||||
|
||||
// first item is always the path
|
||||
let path = Path::from(inner.next().unwrap());
|
||||
|
||||
// check what comes next
|
||||
match inner.next() {
|
||||
None => {
|
||||
// #[path]
|
||||
Attribute::Path(path)
|
||||
}
|
||||
|
||||
Some(next) => match next.as_rule() {
|
||||
Rule::primary => {
|
||||
// #[path = literal]
|
||||
Attribute::NameValue {
|
||||
path,
|
||||
value: Literal::from(next),
|
||||
}
|
||||
}
|
||||
|
||||
Rule::meta_list => {
|
||||
// #[path(...)]
|
||||
let items = next.into_inner().map(Attribute::from).collect();
|
||||
|
||||
Attribute::List { path, items }
|
||||
}
|
||||
|
||||
_ => unreachable!("unexpected rule in meta: {:?}", next.as_rule()),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
Rule::meta_list => {
|
||||
// This case usually won't be hit directly,
|
||||
// but it's nice to keep it safe if reused
|
||||
let items = pair.into_inner().map(Attribute::from).collect::<Vec<_>>();
|
||||
|
||||
// NOTE: this shouldn't normally construct an Attribute alone
|
||||
// but you can panic or wrap depending on your design
|
||||
panic!("meta_list should be handled inside meta: {:?}", items);
|
||||
}
|
||||
|
||||
_ => unreachable!("unexpected rule: {:?}", pair.as_rule()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<pest::iterators::Pair<'_, Rule>> for TopLevel {
|
||||
fn from(pair: pest::iterators::Pair<'_, Rule>) -> Self {
|
||||
let mut inner = pair.into_inner();
|
||||
|
||||
let attributes = inner
|
||||
.next()
|
||||
.unwrap()
|
||||
.into_inner()
|
||||
.map(Attribute::from)
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
TopLevel(
|
||||
inner
|
||||
.next()
|
||||
.map(TopLevelKind::from)
|
||||
.unwrap_or(TopLevelKind::ModAttribute),
|
||||
attributes,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<pest::iterators::Pair<'_, Rule>> for TopLevelKind {
|
||||
fn from(pair: pest::iterators::Pair<'_, Rule>) -> Self {
|
||||
let rule = pair.as_rule();
|
||||
let mut inner = pair.into_inner();
|
||||
|
||||
match rule {
|
||||
Rule::import => Ok(TopLevel::Include(StaticPath::from(inner.next().unwrap()))),
|
||||
Rule::import => TopLevelKind::Include(Path::from(inner.next().unwrap())),
|
||||
|
||||
Rule::function_decl => {
|
||||
let export = if let Some(first) = inner.peek() {
|
||||
@@ -152,13 +227,13 @@ impl TryFrom<pest::iterators::Pair<'_, Rule>> for TopLevel {
|
||||
|
||||
let body = Block::from(inner.next().unwrap());
|
||||
|
||||
Ok(TopLevel::FunctionDecl {
|
||||
TopLevelKind::FunctionDecl {
|
||||
export,
|
||||
name,
|
||||
params,
|
||||
return_type,
|
||||
body,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
Rule::struct_decl => {
|
||||
@@ -176,14 +251,12 @@ impl TryFrom<pest::iterators::Pair<'_, Rule>> for TopLevel {
|
||||
let fields_pair = inner.next().unwrap();
|
||||
let fields = FieldList::from(fields_pair);
|
||||
|
||||
Ok(TopLevel::StructDecl {
|
||||
TopLevelKind::StructDecl {
|
||||
export,
|
||||
name,
|
||||
fields,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
Rule::EOI => Err(()),
|
||||
_ => unimplemented!("{rule:#?}"),
|
||||
}
|
||||
}
|
||||
@@ -262,6 +335,23 @@ impl From<pest::iterators::Pair<'_, Rule>> for Statement {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<pest::iterators::Pair<'_, Rule>> for Literal {
|
||||
fn from(pair: pest::iterators::Pair<'_, Rule>) -> Self {
|
||||
let rule = pair.as_rule();
|
||||
let mut inner = pair.clone().into_inner();
|
||||
|
||||
match rule {
|
||||
Rule::primary => Self::from(inner.next().unwrap()),
|
||||
Rule::integer => Literal::Int(pair.as_str().parse::<i64>().unwrap()),
|
||||
Rule::float => Literal::Float(pair.as_str().parse::<f64>().unwrap()),
|
||||
Rule::boolean => Literal::Bool(pair.as_str().parse::<bool>().unwrap()),
|
||||
Rule::string_lit => Literal::String(inner.as_str().to_string()),
|
||||
Rule::tuple => Literal::Tuple(inner.map(Expression::from).collect()),
|
||||
_ => unimplemented!("{rule:#?}"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<pest::iterators::Pair<'_, Rule>> for Expression {
|
||||
fn from(pair: pest::iterators::Pair<Rule>) -> Self {
|
||||
let rule = pair.as_rule();
|
||||
@@ -292,12 +382,20 @@ impl From<pest::iterators::Pair<'_, Rule>> for Expression {
|
||||
}
|
||||
}
|
||||
Rule::primary => Expression::from(inner.next().unwrap()),
|
||||
Rule::static_path => Expression::Path(StaticPath::from(pair)),
|
||||
Rule::integer => Expression::IntLiteral(pair.as_str().parse::<i64>().unwrap()),
|
||||
Rule::float => Expression::FloatLiteral(pair.as_str().parse::<f64>().unwrap()),
|
||||
Rule::boolean => Expression::BoolLiteral(pair.as_str().parse::<bool>().unwrap()),
|
||||
Rule::string_lit => Expression::StringLiteral(inner.as_str().to_string()),
|
||||
Rule::tuple => Expression::TupleLiteral(inner.map(Expression::from).collect()),
|
||||
Rule::static_path => Expression::Path(Path::from(pair)),
|
||||
Rule::integer => {
|
||||
Expression::Literal(Literal::Int(pair.as_str().parse::<i64>().unwrap()))
|
||||
}
|
||||
Rule::float => {
|
||||
Expression::Literal(Literal::Float(pair.as_str().parse::<f64>().unwrap()))
|
||||
}
|
||||
Rule::boolean => {
|
||||
Expression::Literal(Literal::Bool(pair.as_str().parse::<bool>().unwrap()))
|
||||
}
|
||||
Rule::string_lit => Expression::Literal(Literal::String(inner.as_str().to_string())),
|
||||
Rule::tuple => {
|
||||
Expression::Literal(Literal::Tuple(inner.map(Expression::from).collect()))
|
||||
}
|
||||
_ => unimplemented!("{rule:#?}"),
|
||||
}
|
||||
}
|
||||
|
||||
+65
-14
@@ -1,6 +1,7 @@
|
||||
use parser::ast::{
|
||||
BinaryOp, Block, Expression, IfStmt, Postfix, Prefix, Statement, StaticPath, TopLevel,
|
||||
TypeExpr, TypeExprKind, TypePostfix, VarAssignStmt, VarDecl, VarDeclStmt, WhileStmt,
|
||||
Attribute, BinaryOp, Block, Expression, IfStmt, Literal, Path, Postfix, Prefix, Statement,
|
||||
TopLevel, TopLevelKind, TypeExpr, TypeExprKind, TypePostfix, VarAssignStmt, VarDecl,
|
||||
VarDeclStmt, WhileStmt,
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
@@ -105,15 +106,14 @@ impl GetRust for TypeExprKind {
|
||||
}
|
||||
}
|
||||
|
||||
impl GetRust for Expression {
|
||||
impl GetRust for Literal {
|
||||
fn get_rust(&self) -> String {
|
||||
match self {
|
||||
Expression::Path(path) => path.get_rust(),
|
||||
Expression::IntLiteral(n) => n.to_string(),
|
||||
Expression::FloatLiteral(n) => n.to_string(),
|
||||
Expression::BoolLiteral(b) => b.to_string(),
|
||||
Expression::StringLiteral(s) => format!("\"{s}\""),
|
||||
Expression::TupleLiteral(t) => {
|
||||
Self::Int(n) => n.to_string(),
|
||||
Self::Float(n) => format!("{n:?}"),
|
||||
Self::Bool(b) => b.to_string(),
|
||||
Self::String(s) => format!("\"{s}\""),
|
||||
Self::Tuple(t) => {
|
||||
format!(
|
||||
"({})",
|
||||
t.iter()
|
||||
@@ -122,6 +122,15 @@ impl GetRust for Expression {
|
||||
.join(", ")
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl GetRust for Expression {
|
||||
fn get_rust(&self) -> String {
|
||||
match self {
|
||||
Expression::Path(path) => path.get_rust(),
|
||||
Expression::Literal(literal) => literal.get_rust(),
|
||||
Expression::Fix {
|
||||
initial,
|
||||
prefixes,
|
||||
@@ -219,12 +228,54 @@ impl ToRust for Block {
|
||||
|
||||
impl ToRust for TopLevel {
|
||||
fn to_rust(&self, cg: &mut RustCodegen) {
|
||||
match &self.0 {
|
||||
TopLevelKind::ModAttribute => {
|
||||
for attr in &self.1 {
|
||||
cg.addln(&format!("#![{}]", attr.get_rust()));
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
for attr in &self.1 {
|
||||
cg.addln(&format!("#[{}]", attr.get_rust()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
self.0.to_rust(cg);
|
||||
}
|
||||
}
|
||||
|
||||
impl GetRust for Attribute {
|
||||
fn get_rust(&self) -> String {
|
||||
match self {
|
||||
TopLevel::Include(path) => {
|
||||
Self::Path(path) => path.get_rust(),
|
||||
Self::NameValue { path, value } => {
|
||||
format!("{} = {}", path.get_rust(), value.get_rust())
|
||||
}
|
||||
Self::List { path, items } => {
|
||||
format!(
|
||||
"{}({})",
|
||||
path.get_rust(),
|
||||
items
|
||||
.iter()
|
||||
.map(Attribute::get_rust)
|
||||
.collect::<Vec<_>>()
|
||||
.join(", ")
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ToRust for TopLevelKind {
|
||||
fn to_rust(&self, cg: &mut RustCodegen) {
|
||||
match self {
|
||||
Self::ModAttribute => {}
|
||||
Self::Include(path) => {
|
||||
cg.addln(&format!("use {};", path.get_rust()));
|
||||
}
|
||||
|
||||
TopLevel::StructDecl {
|
||||
Self::StructDecl {
|
||||
export,
|
||||
name,
|
||||
fields,
|
||||
@@ -242,7 +293,7 @@ impl ToRust for TopLevel {
|
||||
cg.addln("}\n");
|
||||
}
|
||||
|
||||
TopLevel::FunctionDecl {
|
||||
Self::FunctionDecl {
|
||||
export,
|
||||
name,
|
||||
params,
|
||||
@@ -359,7 +410,7 @@ impl GetRust for VarDecl {
|
||||
}
|
||||
}
|
||||
|
||||
impl GetRust for StaticPath {
|
||||
impl GetRust for Path {
|
||||
fn get_rust(&self) -> String {
|
||||
self.0.join("::")
|
||||
}
|
||||
@@ -374,7 +425,7 @@ impl GetRust for TypePostfix {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_static_type_path(path: &StaticPath) -> String {
|
||||
pub fn get_static_type_path(path: &Path) -> String {
|
||||
let rust_path = path.get_rust();
|
||||
|
||||
if rust_path == "void" {
|
||||
|
||||
+11
-1
@@ -1,3 +1,13 @@
|
||||
#![allow(unused_mut)]
|
||||
|
||||
#[derive(Debug)]
|
||||
public struct ApiCall {
|
||||
i32 x,
|
||||
i32 y,
|
||||
}
|
||||
|
||||
void main() {
|
||||
(i32, i32, str*) my_tuple = (10, 20, "hello, world");
|
||||
ApiCall call = ApiCall { x: 10, y: 12 };
|
||||
|
||||
println!("{call:?}");
|
||||
}
|
||||
Reference in New Issue
Block a user