Merge pull request #47 from mist-go/closures-and-bodies
Closures and fix statement bodies
This commit is contained in:
+31
-13
@@ -85,7 +85,7 @@ impl GenRust for Expression {
|
|||||||
prefixes,
|
prefixes,
|
||||||
postfixes,
|
postfixes,
|
||||||
} => {
|
} => {
|
||||||
cg.add(&prefixes.get_rust());
|
prefixes.gen_rust(ctx, cg);
|
||||||
initial.gen_rust(ctx, cg);
|
initial.gen_rust(ctx, cg);
|
||||||
cg.add(&Some(prefixes).get_rust());
|
cg.add(&Some(prefixes).get_rust());
|
||||||
for postfix in postfixes {
|
for postfix in postfixes {
|
||||||
@@ -110,23 +110,41 @@ impl GenRust for Expression {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl GetRust for Prefix {
|
impl GenRust for Prefix {
|
||||||
fn get_rust(&self) -> String {
|
fn gen_rust(&self, ctx: &mut Context, cg: &mut RustCodegen) {
|
||||||
match self {
|
match self {
|
||||||
Self::Deref => "*",
|
Self::Deref => cg.add("*"),
|
||||||
Self::Ref => "&",
|
Self::Ref => cg.add("&"),
|
||||||
Self::RefMut => "&mut ",
|
Self::RefMut => cg.add("&mut "),
|
||||||
Self::Not => "!",
|
Self::Not => cg.add("!"),
|
||||||
Self::New(_) => "",
|
Self::New(_) => cg.add(""),
|
||||||
Self::Neg => "-",
|
Self::Neg => cg.add("-"),
|
||||||
|
Self::Closure(ty, args) => {
|
||||||
|
cg.add("|");
|
||||||
|
for (i, arg) in args.iter().enumerate() {
|
||||||
|
if i > 0 {
|
||||||
|
cg.add(", ");
|
||||||
|
}
|
||||||
|
|
||||||
|
arg.gen_rust(ctx, cg);
|
||||||
|
}
|
||||||
|
cg.add("| ");
|
||||||
|
|
||||||
|
if let Some(ty) = ty {
|
||||||
|
cg.add("-> ");
|
||||||
|
cg.add(&ty.get_rust());
|
||||||
|
cg.add(" ");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.to_string()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl GetRust for Vec<Prefix> {
|
impl GenRust for Vec<Prefix> {
|
||||||
fn get_rust(&self) -> String {
|
fn gen_rust(&self, ctx: &mut Context, cg: &mut RustCodegen) {
|
||||||
self.into_iter().map(Prefix::get_rust).collect()
|
for prefix in self {
|
||||||
|
prefix.gen_rust(ctx, cg);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -94,6 +94,17 @@ impl RustCodegen {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn ensure_brackets_body(&mut self, ctx: &mut Context, body: &StatementBody) {
|
||||||
|
match body {
|
||||||
|
StatementBody::Expression(expr) => self.ensure_brackets_expr(ctx, expr),
|
||||||
|
|
||||||
|
StatementBody::Statement(expr) => {
|
||||||
|
ctx.expr_ensure_semicolon = true;
|
||||||
|
self.ensure_brackets_expr(ctx, expr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl GenRust for Attribute {
|
impl GenRust for Attribute {
|
||||||
|
|||||||
@@ -26,6 +26,18 @@ impl GenRust for Block {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl GenRust for StatementBody {
|
||||||
|
fn gen_rust(&self, ctx: &mut Context, cg: &mut RustCodegen) {
|
||||||
|
match self {
|
||||||
|
Self::Expression(expr) => expr.gen_rust(ctx, cg),
|
||||||
|
Self::Statement(stmt) => {
|
||||||
|
ctx.expr_ensure_semicolon = true;
|
||||||
|
stmt.gen_rust(ctx, cg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl GenRust for Statement {
|
impl GenRust for Statement {
|
||||||
fn gen_rust(&self, ctx: &mut Context, cg: &mut RustCodegen) {
|
fn gen_rust(&self, ctx: &mut Context, cg: &mut RustCodegen) {
|
||||||
match self {
|
match self {
|
||||||
@@ -76,18 +88,18 @@ impl GenRust for Statement {
|
|||||||
cg.add("if ");
|
cg.add("if ");
|
||||||
initial.condition.gen_rust(ctx, cg);
|
initial.condition.gen_rust(ctx, cg);
|
||||||
cg.add(" ");
|
cg.add(" ");
|
||||||
cg.ensure_brackets_expr(ctx, &initial.body);
|
cg.ensure_brackets_body(ctx, &initial.body);
|
||||||
|
|
||||||
for else_if_branch in else_if {
|
for else_if_branch in else_if {
|
||||||
cg.add("else if");
|
cg.add("else if");
|
||||||
else_if_branch.condition.gen_rust(ctx, cg);
|
else_if_branch.condition.gen_rust(ctx, cg);
|
||||||
cg.add(" ");
|
cg.add(" ");
|
||||||
cg.ensure_brackets_expr(ctx, &else_if_branch.body);
|
cg.ensure_brackets_body(ctx, &else_if_branch.body);
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(else_br) = else_branch {
|
if let Some(else_br) = else_branch {
|
||||||
cg.add(" else ");
|
cg.add(" else ");
|
||||||
cg.ensure_brackets_expr(ctx, else_br);
|
cg.ensure_brackets_body(ctx, else_br);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -95,12 +107,12 @@ impl GenRust for Statement {
|
|||||||
cg.add("while ");
|
cg.add("while ");
|
||||||
condition.gen_rust(ctx, cg);
|
condition.gen_rust(ctx, cg);
|
||||||
cg.add(" ");
|
cg.add(" ");
|
||||||
cg.ensure_brackets_expr(ctx, body);
|
cg.ensure_brackets_body(ctx, body);
|
||||||
}
|
}
|
||||||
|
|
||||||
Statement::Loop(body) => {
|
Statement::Loop(body) => {
|
||||||
cg.add("loop ");
|
cg.add("loop ");
|
||||||
cg.ensure_brackets_expr(ctx, body);
|
cg.ensure_brackets_body(ctx, body);
|
||||||
}
|
}
|
||||||
|
|
||||||
Statement::CStyleFor {
|
Statement::CStyleFor {
|
||||||
@@ -156,7 +168,7 @@ impl GenRust for Statement {
|
|||||||
pattern.gen_rust(ctx, cg);
|
pattern.gen_rust(ctx, cg);
|
||||||
cg.add(" in ");
|
cg.add(" in ");
|
||||||
iterator.gen_rust(ctx, cg);
|
iterator.gen_rust(ctx, cg);
|
||||||
cg.ensure_brackets_expr(ctx, body);
|
cg.ensure_brackets_body(ctx, body);
|
||||||
}
|
}
|
||||||
|
|
||||||
Statement::Return(expr) => {
|
Statement::Return(expr) => {
|
||||||
|
|||||||
@@ -62,6 +62,7 @@ pub enum Prefix {
|
|||||||
New(Option<Generics>),
|
New(Option<Generics>),
|
||||||
Not,
|
Not,
|
||||||
Neg,
|
Neg,
|
||||||
|
Closure(Option<TypeExpr>, Vec<VarDecl>),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize)]
|
#[derive(Debug, Clone, Serialize)]
|
||||||
|
|||||||
@@ -8,27 +8,33 @@ pub struct Block(
|
|||||||
pub Option<Spanned<Expression>>,
|
pub Option<Spanned<Expression>>,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize)]
|
||||||
|
pub enum StatementBody {
|
||||||
|
Statement(Expression),
|
||||||
|
Expression(Expression),
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize)]
|
#[derive(Debug, Clone, Serialize)]
|
||||||
pub enum Statement {
|
pub enum Statement {
|
||||||
Block(Block),
|
Block(Block),
|
||||||
If {
|
If {
|
||||||
initial: StatementBranch,
|
initial: StatementBranch,
|
||||||
else_if: Vec<StatementBranch>,
|
else_if: Vec<StatementBranch>,
|
||||||
else_branch: Option<Box<Expression>>,
|
else_branch: Option<StatementBody>,
|
||||||
},
|
},
|
||||||
Loop(Expression),
|
Loop(StatementBody),
|
||||||
While(StatementBranch),
|
While(StatementBranch),
|
||||||
CStyleFor {
|
CStyleFor {
|
||||||
init: Expression,
|
init: Expression,
|
||||||
condition: Expression,
|
condition: Expression,
|
||||||
update: Expression,
|
update: Expression,
|
||||||
body: Expression,
|
body: StatementBody,
|
||||||
},
|
},
|
||||||
For {
|
For {
|
||||||
mutable: bool,
|
mutable: bool,
|
||||||
pattern: Pattern,
|
pattern: Pattern,
|
||||||
iterator: Expression,
|
iterator: Expression,
|
||||||
body: Box<Expression>,
|
body: StatementBody,
|
||||||
},
|
},
|
||||||
Match(Expression, Vec<(Vec<Pattern>, Expression)>),
|
Match(Expression, Vec<(Vec<Pattern>, Expression)>),
|
||||||
|
|
||||||
@@ -54,28 +60,28 @@ pub struct VarDeclStmt {
|
|||||||
#[derive(Debug, Clone, Serialize)]
|
#[derive(Debug, Clone, Serialize)]
|
||||||
pub struct StatementBranch {
|
pub struct StatementBranch {
|
||||||
pub condition: Expression,
|
pub condition: Expression,
|
||||||
pub body: Box<Expression>,
|
pub body: Box<StatementBody>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Statement {
|
impl Statement {
|
||||||
pub fn is_block(&self) -> bool {
|
pub fn is_block(&self) -> bool {
|
||||||
match self {
|
match self {
|
||||||
Self::Block(_) => true,
|
Self::Block(_)
|
||||||
Self::If {
|
| Self::Match(_, _)
|
||||||
initial,
|
| Self::While(_)
|
||||||
else_if,
|
| Self::For { .. }
|
||||||
else_branch,
|
| Self::Loop(..)
|
||||||
} => {
|
| Self::CStyleFor { .. }
|
||||||
else_branch
|
| Self::If { .. } => true,
|
||||||
.as_ref()
|
_ => false,
|
||||||
.map(|v| v.is_block())
|
}
|
||||||
.unwrap_or_default()
|
}
|
||||||
|| else_if
|
}
|
||||||
.last()
|
|
||||||
.map(|b| b.body.is_block())
|
impl StatementBody {
|
||||||
.unwrap_or_default()
|
pub fn is_soft_return(&self) -> bool {
|
||||||
|| initial.body.is_block()
|
match self {
|
||||||
}
|
Self::Expression(_) => true,
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -91,7 +91,7 @@ generics = { "<" ~ (generic ~ ("," ~ generic)*)? ~ ">" }
|
|||||||
// ======================================================
|
// ======================================================
|
||||||
|
|
||||||
tuple_type = {
|
tuple_type = {
|
||||||
"(" ~ (type_expr ~ ("," ~ type_expr)*)? ~ ")"
|
"[" ~ (type_expr ~ ("," ~ type_expr)*)? ~ "]"
|
||||||
}
|
}
|
||||||
|
|
||||||
path_type = {
|
path_type = {
|
||||||
@@ -343,6 +343,10 @@ statement = _{
|
|||||||
| (expr ~ semicolon)
|
| (expr ~ semicolon)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
statement_wrapper = { statement }
|
||||||
|
|
||||||
|
statement_body = { statement_wrapper | expr }
|
||||||
|
|
||||||
// ------------------------------------------------------
|
// ------------------------------------------------------
|
||||||
// BASIC STATEMENTS
|
// BASIC STATEMENTS
|
||||||
// ------------------------------------------------------
|
// ------------------------------------------------------
|
||||||
@@ -384,7 +388,7 @@ control_flow = {
|
|||||||
| block
|
| block
|
||||||
}
|
}
|
||||||
|
|
||||||
statement_branch = { "(" ~ expr ~ ")" ~ statement }
|
statement_branch = { "(" ~ expr ~ ")" ~ statement_body }
|
||||||
|
|
||||||
else_if = {
|
else_if = {
|
||||||
"else" ~ "if" ~ statement_branch
|
"else" ~ "if" ~ statement_branch
|
||||||
@@ -395,7 +399,7 @@ else_if_list = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if_stmt = {
|
if_stmt = {
|
||||||
"if" ~ statement_branch ~ else_if_list ~ ("else" ~ statement)?
|
"if" ~ statement_branch ~ else_if_list ~ ("else" ~ statement_body)?
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------
|
// ------------------------------------------------------
|
||||||
@@ -407,15 +411,15 @@ while_stmt = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
c_for_stmt = {
|
c_for_stmt = {
|
||||||
"for" ~ "(" ~ statement ~ statement ~ expr ~ ")" ~ statement
|
"for" ~ "(" ~ statement ~ statement ~ expr ~ ")" ~ statement_body
|
||||||
}
|
}
|
||||||
|
|
||||||
for_stmt = {
|
for_stmt = {
|
||||||
"for" ~ "(" ~ mutable? ~ pattern ~ ":" ~ expr ~ ")" ~ statement
|
"for" ~ "(" ~ mutable? ~ pattern ~ ":" ~ expr ~ ")" ~ statement_body
|
||||||
}
|
}
|
||||||
|
|
||||||
loop_stmt = {
|
loop_stmt = {
|
||||||
"loop" ~ statement
|
"loop" ~ statement_body
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------
|
// ------------------------------------------------------
|
||||||
@@ -436,6 +440,12 @@ match_stmt = {
|
|||||||
// EXPRESSIONS
|
// EXPRESSIONS
|
||||||
// ======================================================
|
// ======================================================
|
||||||
|
|
||||||
|
// ------------------------------------------------------
|
||||||
|
// CLOSURES
|
||||||
|
// ------------------------------------------------------
|
||||||
|
|
||||||
|
closure = { type_expr? ~ "|" ~ param_list ~ "|" }
|
||||||
|
|
||||||
// ------------------------------------------------------
|
// ------------------------------------------------------
|
||||||
// TUPLES & ARRAYS
|
// TUPLES & ARRAYS
|
||||||
// ------------------------------------------------------
|
// ------------------------------------------------------
|
||||||
@@ -549,7 +559,8 @@ not_px = { "!" }
|
|||||||
neg_px = { "-" }
|
neg_px = { "-" }
|
||||||
|
|
||||||
prefix = {
|
prefix = {
|
||||||
deref_px
|
closure
|
||||||
|
| deref_px
|
||||||
| mut_ref_px
|
| mut_ref_px
|
||||||
| ref_px
|
| ref_px
|
||||||
| new_px
|
| new_px
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ use crate::{
|
|||||||
ast::*,
|
ast::*,
|
||||||
ast_ensure, ast_expr,
|
ast_ensure, ast_expr,
|
||||||
error::{AstError, AstResult, GetLength, IntoErr, collect_recovered, collect_recovered_map},
|
error::{AstError, AstResult, GetLength, IntoErr, collect_recovered, collect_recovered_map},
|
||||||
|
parser::consume_rule,
|
||||||
};
|
};
|
||||||
use pest::pratt_parser::PrattParser;
|
use pest::pratt_parser::PrattParser;
|
||||||
use std::sync::OnceLock;
|
use std::sync::OnceLock;
|
||||||
@@ -12,7 +13,7 @@ impl<'a> TryFrom<pest::iterators::Pair<'a, Rule>> for Expression {
|
|||||||
|
|
||||||
fn try_from(pair: pest::iterators::Pair<'a, Rule>) -> Result<Self, Self::Error> {
|
fn try_from(pair: pest::iterators::Pair<'a, Rule>) -> Result<Self, Self::Error> {
|
||||||
let rule = pair.as_rule();
|
let rule = pair.as_rule();
|
||||||
let inner = pair.clone().into_inner();
|
let mut inner = pair.clone().into_inner();
|
||||||
|
|
||||||
match rule {
|
match rule {
|
||||||
Rule::expr => {
|
Rule::expr => {
|
||||||
@@ -78,6 +79,15 @@ impl<'a> TryFrom<pest::iterators::Pair<'a, Rule>> for Expression {
|
|||||||
Rule::static_path => ast_expr!(Expression::Path(pair.try_into())),
|
Rule::static_path => ast_expr!(Expression::Path(pair.try_into())),
|
||||||
Rule::literal => ast_expr!(Expression::Literal(pair.try_into())),
|
Rule::literal => ast_expr!(Expression::Literal(pair.try_into())),
|
||||||
Rule::expr_path => ast_expr!(Expression::Path(pair.try_into())),
|
Rule::expr_path => ast_expr!(Expression::Path(pair.try_into())),
|
||||||
|
Rule::statement_wrapper => {
|
||||||
|
let i = inner.next().unwrap();
|
||||||
|
match i.as_rule() {
|
||||||
|
Rule::expr => i.try_into(),
|
||||||
|
_ => ast_expr!(Expression::Statement(
|
||||||
|
i.try_into().get_map(Box::new).map(Box::new)
|
||||||
|
)),
|
||||||
|
}
|
||||||
|
}
|
||||||
Rule::statement | Rule::basic_stmt | Rule::control_flow => ast_expr!(
|
Rule::statement | Rule::basic_stmt | Rule::control_flow => ast_expr!(
|
||||||
Expression::Statement(pair.try_into().get_map(Box::new).map(Box::new))
|
Expression::Statement(pair.try_into().get_map(Box::new).map(Box::new))
|
||||||
),
|
),
|
||||||
@@ -104,6 +114,16 @@ impl<'a> TryFrom<pest::iterators::Pair<'a, Rule>> for Prefix {
|
|||||||
),
|
),
|
||||||
Rule::not_px => Self::Not,
|
Rule::not_px => Self::Not,
|
||||||
Rule::neg_px => Self::Neg,
|
Rule::neg_px => Self::Neg,
|
||||||
|
Rule::closure => {
|
||||||
|
let mut inner = pair.into_inner();
|
||||||
|
|
||||||
|
return ast_expr!(Self::Closure(
|
||||||
|
consume_rule(&mut inner, Rule::type_expr)
|
||||||
|
.map(TypeExpr::try_from)
|
||||||
|
.transpose(),
|
||||||
|
collect_recovered(inner.next().unwrap().into_inner())
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
_ => return AstError::bug_unimplemented(pair),
|
_ => return AstError::bug_unimplemented(pair),
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -18,6 +18,24 @@ impl<'a> TryFrom<pest::iterators::Pair<'a, Rule>> for Block {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'a> TryFrom<pest::iterators::Pair<'a, Rule>> for StatementBody {
|
||||||
|
type Error = AstError<'a, Self>;
|
||||||
|
|
||||||
|
fn try_from(pair: pest::iterators::Pair<'a, Rule>) -> Result<Self, Self::Error> {
|
||||||
|
let mut inner = pair.clone().into_inner();
|
||||||
|
|
||||||
|
ast_ensure!(pair, Rule::statement_body => {
|
||||||
|
let i = inner.next().unwrap();
|
||||||
|
|
||||||
|
match i.as_rule() {
|
||||||
|
Rule::expr => ast_expr!(StatementBody::Expression(i.try_into())),
|
||||||
|
Rule::statement_wrapper => ast_expr!(StatementBody::Statement(i.try_into())),
|
||||||
|
_ => AstError::bug_unimplemented(i),
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'a> TryFrom<pest::iterators::Pair<'a, Rule>> for StatementBranch {
|
impl<'a> TryFrom<pest::iterators::Pair<'a, Rule>> for StatementBranch {
|
||||||
type Error = AstError<'a, Self>;
|
type Error = AstError<'a, Self>;
|
||||||
|
|
||||||
@@ -63,12 +81,7 @@ impl<'a> TryFrom<pest::iterators::Pair<'a, Rule>> for Statement {
|
|||||||
ast_expr!(Statement::If {
|
ast_expr!(Statement::If {
|
||||||
initial: inner.next().unwrap().try_into(),
|
initial: inner.next().unwrap().try_into(),
|
||||||
else_if: collect_recovered(inner.next().unwrap().into_inner()),
|
else_if: collect_recovered(inner.next().unwrap().into_inner()),
|
||||||
else_branch: inner
|
else_branch: inner.next().map(StatementBody::try_from).transpose(),
|
||||||
.next()
|
|
||||||
.map(Expression::try_from)
|
|
||||||
.transpose()
|
|
||||||
.map(|v| v.map(Box::new))
|
|
||||||
.get_map(|v| { Some(Box::new(v)) }),
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -87,7 +100,7 @@ impl<'a> TryFrom<pest::iterators::Pair<'a, Rule>> for Statement {
|
|||||||
mutable: Ok(listen_rule(&mut inner, Rule::mutable)) as AstResult<'_, bool>,
|
mutable: Ok(listen_rule(&mut inner, Rule::mutable)) as AstResult<'_, bool>,
|
||||||
pattern: inner.next().unwrap().try_into(),
|
pattern: inner.next().unwrap().try_into(),
|
||||||
iterator: inner.next().unwrap().try_into(),
|
iterator: inner.next().unwrap().try_into(),
|
||||||
body: inner.next().unwrap().try_into().map(Box::new),
|
body: inner.next().unwrap().try_into(),
|
||||||
}),
|
}),
|
||||||
|
|
||||||
Rule::match_stmt => ast_expr!(Statement::Match(
|
Rule::match_stmt => ast_expr!(Statement::Match(
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
pub enum Event {
|
pub enum Event {
|
||||||
Startup,
|
Startup,
|
||||||
Shutdown,
|
Shutdown,
|
||||||
TaskExecuted(String),
|
TaskExecuted[String],
|
||||||
PluginLoaded(String),
|
PluginLoaded[String],
|
||||||
Error(String),
|
Error[String],
|
||||||
}
|
}
|
||||||
+17
-1
@@ -9,4 +9,20 @@ void main() {
|
|||||||
|
|
||||||
app_instance.boot();
|
app_instance.boot();
|
||||||
app_instance.run();
|
app_instance.run();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void do_stuff() {
|
||||||
|
vec!(1, 2, 3).into_iter().map(Option<i32> |var v| {Some(v)}).collect::<Vec<_>>();
|
||||||
|
|
||||||
|
if (43==69) testing1();
|
||||||
|
}
|
||||||
|
|
||||||
|
i32 testing1() {
|
||||||
|
|
||||||
|
i32 v = if (0 == 0) {
|
||||||
|
0
|
||||||
|
} else {
|
||||||
|
1
|
||||||
|
};
|
||||||
|
v
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user