update
BinOp, UnOp, FunctionCall
This commit is contained in:
parent
3e7bb062aa
commit
2ca5c18d66
@ -13,40 +13,34 @@ fn is_standard_library(name: String) -> bool {
|
||||
}
|
||||
|
||||
pub struct ConstantFolder {
|
||||
locals: Vec<expression_reducer::Variable>
|
||||
locals: Box<Vec<expression_reducer::Variable>>
|
||||
}
|
||||
|
||||
impl ConstantFolder {
|
||||
pub fn new() -> Self {
|
||||
ConstantFolder{
|
||||
locals: vec![]
|
||||
locals: Box::new(vec![])
|
||||
}
|
||||
}
|
||||
|
||||
fn register_local(&mut self, name: Option<String>, value: Option<Expression>) -> bool {
|
||||
if name.is_none() {
|
||||
return false
|
||||
}
|
||||
self.locals.push(
|
||||
expression_reducer::Variable::with_value(
|
||||
name.unwrap(), value, &self.locals
|
||||
));
|
||||
true
|
||||
}
|
||||
|
||||
fn assign(&mut self, name: Option<String>, value: Option<Expression>) -> bool {
|
||||
if name.is_none() {
|
||||
return false
|
||||
}
|
||||
fn register_local(&mut self, name: String, value: Option<Expression>) {
|
||||
let locals = &*self.locals;
|
||||
let var = expression_reducer::Variable::with_value(
|
||||
name.unwrap(), value, &self.locals
|
||||
name, value, locals
|
||||
);
|
||||
self.locals.push(var);
|
||||
}
|
||||
|
||||
fn assign(&mut self, name: String, value: Option<Expression>) {
|
||||
let locals = &*self.locals;
|
||||
let var = expression_reducer::Variable::with_value(
|
||||
name, value, locals
|
||||
);
|
||||
{
|
||||
let mut iter = self.locals.iter_mut();
|
||||
let it = iter.find(|it| it.name() == var.name());
|
||||
it.map(|old| old.assign_value(var));
|
||||
};
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
@ -54,20 +48,22 @@ impl Visitor for ConstantFolder {
|
||||
fn visit_assignment<'a>(&mut self, assignment: &Assignment<'a>) {
|
||||
let mut names = assignment.variables().iter();
|
||||
let mut expressions = assignment.expressions().iter();
|
||||
|
||||
loop {
|
||||
let name = names.next().map(|x| match x {
|
||||
Var::Expression(var_expr) => {
|
||||
var_expr.to_string()
|
||||
Var::Expression(_var_expr) => {
|
||||
panic!("assignment Var::Expression is not supported")
|
||||
}
|
||||
Var::Name(n) => n.token().to_string(),
|
||||
_ => {
|
||||
"".to_string()
|
||||
}
|
||||
_ => unreachable!()
|
||||
});
|
||||
let expr = expressions.next().map(|x| x.clone() /* reduced */);
|
||||
if !self.assign(name, expr) {
|
||||
break
|
||||
match name {
|
||||
Some(name) => {
|
||||
self.assign(name, expr);
|
||||
}
|
||||
None => {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -78,6 +74,8 @@ impl Visitor for ConstantFolder {
|
||||
|
||||
fn visit_function_call<'a>(&mut self, function_call: &FunctionCall<'a>) {
|
||||
println!("visit function_call {}", function_call);
|
||||
let reduced = expression_reducer::reduce_expression_value_function_call(function_call.clone(), &*self.locals);
|
||||
println!("{:?}", reduced);
|
||||
}
|
||||
|
||||
fn visit_function_declaration<'a>(&mut self, function_declaration: &FunctionDeclaration<'a>) {
|
||||
@ -99,8 +97,13 @@ impl Visitor for ConstantFolder {
|
||||
loop {
|
||||
let name = names.next().map(|x| x.token().to_string());
|
||||
let expr = expressions.next().map(|x| x.clone() /* reduced */);
|
||||
if !self.register_local(name, expr) {
|
||||
break
|
||||
match name {
|
||||
Some(name) => {
|
||||
self.register_local(name, expr);
|
||||
}
|
||||
None => {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -58,38 +58,19 @@
|
||||
|
||||
use full_moon::ast;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum VariableType {
|
||||
Number,
|
||||
String,
|
||||
Boolean,
|
||||
// Function(Vec<VariableType>, Vec<VariableType>), // name, param, result
|
||||
// Array(Box<VariableType>),
|
||||
// Dict(Box<VariableType>),
|
||||
// Module(String, String),
|
||||
Function,
|
||||
Array,
|
||||
Dict,
|
||||
Module,
|
||||
Nil,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Variable {
|
||||
n: String, // name
|
||||
t: VariableType,
|
||||
v: Option<Expression>
|
||||
n: String,
|
||||
v: Expression
|
||||
}
|
||||
|
||||
impl Variable {
|
||||
pub fn with_value(name: String, expr: Option<ast::Expression>, locals: &Vec<Variable>) -> Self {
|
||||
let v = Expression::reduce(expr, locals);
|
||||
let t = v.as_ref().map_or(VariableType::Nil, |x| x.assume_type(locals));
|
||||
println!("variable_with {} = {:?}", name, v);
|
||||
Self {
|
||||
n: name,
|
||||
v: v,
|
||||
t: t,
|
||||
}
|
||||
}
|
||||
|
||||
@ -100,38 +81,117 @@ impl Variable {
|
||||
pub fn assign_value(&mut self, var: Self) {
|
||||
println!("variable_assign {} = {:?}", self.n, var.v);
|
||||
self.v = var.v;
|
||||
self.t = var.t;
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum Expression {
|
||||
pub enum BinOp {
|
||||
And,
|
||||
Caret,
|
||||
GreaterThan,
|
||||
GreaterThanEqual,
|
||||
LessThan,
|
||||
LessThanEqual,
|
||||
Minus,
|
||||
Or,
|
||||
Percent,
|
||||
Plus,
|
||||
Slash,
|
||||
Star,
|
||||
TildeEqual,
|
||||
TwoDots,
|
||||
TwoEqual,
|
||||
}
|
||||
|
||||
impl BinOp {
|
||||
fn from<'a>(binop: ast::BinOp<'a>) -> Self {
|
||||
match binop {
|
||||
ast::BinOp::And(_) => BinOp::And,
|
||||
ast::BinOp::Caret(_) => BinOp::Caret,
|
||||
ast::BinOp::GreaterThan(_) => BinOp::GreaterThan,
|
||||
ast::BinOp::GreaterThanEqual(_) => BinOp::GreaterThanEqual,
|
||||
ast::BinOp::LessThan(_) => BinOp::LessThan,
|
||||
ast::BinOp::LessThanEqual(_) => BinOp::LessThanEqual,
|
||||
ast::BinOp::Minus(_) => BinOp::Minus,
|
||||
ast::BinOp::Or(_) => BinOp::Or,
|
||||
ast::BinOp::Percent(_) => BinOp::Percent,
|
||||
ast::BinOp::Plus(_) => BinOp::Plus,
|
||||
ast::BinOp::Slash(_) => BinOp::Slash,
|
||||
ast::BinOp::Star(_) => BinOp::Star,
|
||||
ast::BinOp::TildeEqual(_) => BinOp::TildeEqual,
|
||||
ast::BinOp::TwoDots(_) => BinOp::TwoDots,
|
||||
ast::BinOp::TwoEqual(_) => BinOp::TwoEqual,
|
||||
_ => unreachable!()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum UnOp {
|
||||
Minus,
|
||||
Not,
|
||||
Hash,
|
||||
}
|
||||
|
||||
impl UnOp {
|
||||
fn from<'a>(unop: ast::UnOp<'a>) -> Self {
|
||||
match unop {
|
||||
ast::UnOp::Minus(_) => UnOp::Minus,
|
||||
ast::UnOp::Not(_) => UnOp::Not,
|
||||
ast::UnOp::Hash(_) => UnOp::Hash,
|
||||
_ => unreachable!()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum ExpressionType {
|
||||
Number(f64),
|
||||
Boolean(bool),
|
||||
String(String),
|
||||
Var(String),
|
||||
Var(String), // name
|
||||
FunctionCall(String, Vec<Expression>), // name, param
|
||||
BinOp(Box<Expression>, Box<Expression>, BinOp), // lhs, rhs, binop
|
||||
UnOp(Box<Expression>, UnOp),
|
||||
Index(Box<Expression>, Vec<Expression>), // name, index expr
|
||||
Nil,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Expression {
|
||||
t: ExpressionType,
|
||||
}
|
||||
|
||||
impl Expression {
|
||||
pub fn reduce(expr: Option<ast::Expression>, locals: &Vec<Variable>) -> Option<Self> {
|
||||
pub fn reduce(expr: Option<ast::Expression>, locals: &Vec<Variable>) -> Self {
|
||||
if expr.is_none() {
|
||||
return None
|
||||
Expression{
|
||||
t: ExpressionType::Nil,
|
||||
}
|
||||
} else {
|
||||
let expr = expr.unwrap();
|
||||
reduce_expression(expr, locals)
|
||||
}
|
||||
let expr = expr.unwrap();
|
||||
Some(reduce_expression(expr, locals))
|
||||
}
|
||||
|
||||
pub fn assume_type(&self, locals: &Vec<Variable>) -> VariableType {
|
||||
match self {
|
||||
Expression::Number(_) => { VariableType::Number }
|
||||
Expression::Boolean(_) => { VariableType::Boolean }
|
||||
Expression::String(_) => { VariableType::String }
|
||||
Expression::Var(_) => {
|
||||
VariableType::Number
|
||||
}
|
||||
_ => {
|
||||
VariableType::Nil
|
||||
}
|
||||
fn is_number(&self) -> bool {
|
||||
match self.t {
|
||||
ExpressionType::Number(_) => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
fn is_string(&self) -> bool {
|
||||
match self.t {
|
||||
ExpressionType::String(_) => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
fn is_boolean(&self) -> bool {
|
||||
match self.t {
|
||||
ExpressionType::Boolean(_) => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -175,23 +235,38 @@ fn reduce_expression_value(value: ast::Value, locals: &Vec<Variable>) -> Express
|
||||
panic!("reduce Expression::Function is unsupported");
|
||||
}
|
||||
ast::Value::FunctionCall(function_call) => {
|
||||
panic!("reduce Expression::FunctionCall is unsupported");
|
||||
reduce_expression_value_function_call(function_call, locals)
|
||||
}
|
||||
ast::Value::TableConstructor(table_constructor) => {
|
||||
panic!("reduce Expression::TableConstructor is unsupported");
|
||||
}
|
||||
ast::Value::Number(number) => {
|
||||
let num = number.token().to_string();
|
||||
Expression::Number(num.parse::<f64>().unwrap())
|
||||
Expression{
|
||||
t: ExpressionType::Number(num.parse::<f64>().unwrap()),
|
||||
}
|
||||
}
|
||||
ast::Value::ParenthesesExpression(parentheses_expression) => {
|
||||
reduce_expression(parentheses_expression, locals)
|
||||
}
|
||||
ast::Value::String(string) => {
|
||||
Expression::String(string.token().to_string())
|
||||
Expression{
|
||||
t: ExpressionType::String(string.token().to_string()),
|
||||
}
|
||||
}
|
||||
ast::Value::Symbol(symbol) => {
|
||||
panic!("reduce Expression::Symbol is unsupported");
|
||||
let s = symbol.token().to_string();
|
||||
if s == "true" {
|
||||
Expression{
|
||||
t: ExpressionType::Boolean(true),
|
||||
}
|
||||
} else if s == "false" {
|
||||
Expression{
|
||||
t: ExpressionType::Boolean(false),
|
||||
}
|
||||
} else {
|
||||
panic!("reduce Expression::Symbol is not true/false");
|
||||
}
|
||||
}
|
||||
ast::Value::Var(var) => {
|
||||
reduce_expression_value_var(var, locals)
|
||||
@ -212,7 +287,7 @@ fn reduce_expression_value_var(var: ast::Var, locals: &Vec<Variable>) -> Express
|
||||
panic!("local variable not found")
|
||||
}
|
||||
Some(v) => {
|
||||
v.v.as_ref().unwrap().clone()
|
||||
v.v.clone()
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -220,141 +295,150 @@ fn reduce_expression_value_var(var: ast::Var, locals: &Vec<Variable>) -> Express
|
||||
}
|
||||
}
|
||||
|
||||
pub fn reduce_expression_value_function_call(function_call: ast::FunctionCall, locals: &Vec<Variable>) -> Expression {
|
||||
let function_name = match function_call.prefix() {
|
||||
ast::Prefix::Name(name) => name.token().to_string(),
|
||||
_ => panic!("Function name as expression is unsupported")
|
||||
};
|
||||
let args = {
|
||||
let suf = function_call.suffixes().next().unwrap();
|
||||
match suf {
|
||||
ast::Suffix::Call(ast::Call::AnonymousCall(ast::FunctionArgs::Parentheses{
|
||||
arguments,
|
||||
..
|
||||
})) => {
|
||||
arguments.iter().map(|x| reduce_expression(x.clone(), locals)).collect::<Vec<_>>()
|
||||
}
|
||||
_ => panic!("Index not supported")
|
||||
}
|
||||
};
|
||||
Expression {
|
||||
t: ExpressionType::FunctionCall(function_name, args)
|
||||
}
|
||||
}
|
||||
|
||||
fn apply_binary_operator(lhs: Expression, rhs: Expression, binop: ast::BinOp) -> Expression {
|
||||
match binop {
|
||||
ast::BinOp::And(_) => {
|
||||
panic!("Binary And unimplemented")
|
||||
}
|
||||
ast::BinOp::Caret(_) => {
|
||||
panic!("Binary Caret unimplemented")
|
||||
}
|
||||
ast::BinOp::GreaterThan(_) => {
|
||||
match (lhs, rhs) {
|
||||
(Expression::Number(lhs_), Expression::Number(rhs_)) => {
|
||||
Expression::Boolean(lhs_ > rhs_)
|
||||
match (&lhs.t, &rhs.t) {
|
||||
(&ExpressionType::Number(lhs_), &ExpressionType::Number(rhs_)) => {
|
||||
match binop {
|
||||
ast::BinOp::GreaterThan(_) => {
|
||||
return Expression {
|
||||
t: ExpressionType::Boolean(lhs_ > rhs_),
|
||||
}
|
||||
},
|
||||
ast::BinOp::GreaterThanEqual(_) => {
|
||||
return Expression {
|
||||
t: ExpressionType::Boolean(lhs_ >= rhs_),
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
panic!("Binary GreaterThan wrong argument")
|
||||
ast::BinOp::LessThan(_) => {
|
||||
return Expression {
|
||||
t: ExpressionType::Boolean(lhs_ < rhs_),
|
||||
}
|
||||
}
|
||||
ast::BinOp::LessThanEqual(_) => {
|
||||
return Expression {
|
||||
t: ExpressionType::Boolean(lhs_ <= rhs_),
|
||||
}
|
||||
}
|
||||
ast::BinOp::Minus(_) => {
|
||||
return Expression {
|
||||
t: ExpressionType::Number(lhs_ - rhs_),
|
||||
}
|
||||
}
|
||||
ast::BinOp::Percent(_) => {
|
||||
return Expression {
|
||||
t: ExpressionType::Number(lhs_ % rhs_),
|
||||
}
|
||||
}
|
||||
ast::BinOp::Plus(_) => {
|
||||
return Expression {
|
||||
t: ExpressionType::Number(lhs_ + rhs_),
|
||||
}
|
||||
}
|
||||
ast::BinOp::Slash(_) => {
|
||||
return Expression {
|
||||
t: ExpressionType::Number(lhs_ / rhs_),
|
||||
}
|
||||
}
|
||||
ast::BinOp::Star(_) => {
|
||||
return Expression {
|
||||
t: ExpressionType::Number(lhs_ * rhs_),
|
||||
}
|
||||
}
|
||||
ast::BinOp::Caret(_) => {
|
||||
return Expression {
|
||||
t: ExpressionType::Number(lhs_.powf(rhs_)),
|
||||
}
|
||||
}
|
||||
ast::BinOp::TwoEqual(_) => {
|
||||
return Expression {
|
||||
t: ExpressionType::Boolean(lhs_ == rhs_),
|
||||
}
|
||||
}
|
||||
ast::BinOp::TildeEqual(_) => {
|
||||
return Expression {
|
||||
t: ExpressionType::Boolean(lhs_ != rhs_),
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
ast::BinOp::GreaterThanEqual(_) => {
|
||||
match (lhs, rhs) {
|
||||
(Expression::Number(lhs_), Expression::Number(rhs_)) => {
|
||||
Expression::Boolean(lhs_ >= rhs_)
|
||||
_ => {}
|
||||
};
|
||||
|
||||
match (&lhs.t, &rhs.t) {
|
||||
(&ExpressionType::Boolean(lhs_), &ExpressionType::Boolean(rhs_)) => {
|
||||
match binop {
|
||||
ast::BinOp::And(_) => {
|
||||
return Expression {
|
||||
t: ExpressionType::Boolean(lhs_ & rhs_),
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
panic!("Binary GreaterThanEqual wrong argument")
|
||||
ast::BinOp::Or(_) => {
|
||||
return Expression {
|
||||
t: ExpressionType::Boolean(lhs_ | rhs_),
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
ast::BinOp::LessThan(_) => {
|
||||
match (lhs, rhs) {
|
||||
(Expression::Number(lhs_), Expression::Number(rhs_)) => {
|
||||
Expression::Boolean(lhs_ < rhs_)
|
||||
}
|
||||
_ => {
|
||||
panic!("Binary LessThan wrong argument")
|
||||
_ => {}
|
||||
}
|
||||
|
||||
match (&lhs.t, &rhs.t) {
|
||||
(&ExpressionType::String(ref lhs_), &ExpressionType::String(ref rhs_)) => {
|
||||
match binop {
|
||||
ast::BinOp::TwoDots(_) => {
|
||||
return Expression {
|
||||
t: ExpressionType::String(lhs_.clone() + &rhs_),
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
ast::BinOp::LessThanEqual(_) => {
|
||||
match (lhs, rhs) {
|
||||
(Expression::Number(lhs_), Expression::Number(rhs_)) => {
|
||||
Expression::Boolean(lhs_ <= rhs_)
|
||||
}
|
||||
_ => {
|
||||
panic!("Binary LessThanEqual wrong argument")
|
||||
}
|
||||
}
|
||||
}
|
||||
ast::BinOp::Minus(_) => {
|
||||
match (lhs, rhs) {
|
||||
(Expression::Number(lhs_), Expression::Number(rhs_)) => {
|
||||
Expression::Number(lhs_ - rhs_)
|
||||
}
|
||||
_ => {
|
||||
panic!("Binary Minus wrong argument")
|
||||
}
|
||||
}
|
||||
}
|
||||
ast::BinOp::Or(_) => {
|
||||
panic!("Binary Or unimplemented")
|
||||
}
|
||||
ast::BinOp::Percent(_) => {
|
||||
match (lhs, rhs) {
|
||||
(Expression::Number(lhs_), Expression::Number(rhs_)) => {
|
||||
Expression::Number(lhs_ % rhs_)
|
||||
}
|
||||
_ => {
|
||||
panic!("Binary Percent wrong argument")
|
||||
}
|
||||
}
|
||||
}
|
||||
ast::BinOp::Plus(_) => {
|
||||
match (lhs, rhs) {
|
||||
(Expression::Number(lhs_), Expression::Number(rhs_)) => {
|
||||
Expression::Number(lhs_ + rhs_)
|
||||
}
|
||||
_ => {
|
||||
panic!("Binary Plus wrong argument")
|
||||
}
|
||||
}
|
||||
}
|
||||
ast::BinOp::Slash(_) => {
|
||||
match (lhs, rhs) {
|
||||
(Expression::Number(lhs_), Expression::Number(rhs_)) => {
|
||||
Expression::Number(lhs_ / rhs_)
|
||||
}
|
||||
_ => {
|
||||
panic!("Binary Slash wrong argument")
|
||||
}
|
||||
}
|
||||
}
|
||||
ast::BinOp::Star(_) => {
|
||||
match (lhs, rhs) {
|
||||
(Expression::Number(lhs_), Expression::Number(rhs_)) => {
|
||||
Expression::Number(lhs_ * rhs_)
|
||||
}
|
||||
_ => {
|
||||
panic!("Binary Star wrong argument")
|
||||
}
|
||||
}
|
||||
}
|
||||
ast::BinOp::TildeEqual(_) => {
|
||||
panic!("Binary TildeEqual unimplemented")
|
||||
}
|
||||
ast::BinOp::TwoDots(_) => {
|
||||
panic!("Binary TwoDots unimplemented")
|
||||
}
|
||||
ast::BinOp::TwoEqual(_) => {
|
||||
match (lhs, rhs) {
|
||||
(Expression::Number(lhs_), Expression::Number(rhs_)) => {
|
||||
Expression::Boolean(lhs_ == rhs_)
|
||||
}
|
||||
_ => {
|
||||
panic!("Binary TwoEqual wrong argument")
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => unreachable!()
|
||||
_ => {}
|
||||
}
|
||||
|
||||
Expression {
|
||||
t: ExpressionType::BinOp(Box::new(lhs), Box::new(rhs), BinOp::from(binop)),
|
||||
}
|
||||
}
|
||||
|
||||
fn apply_unary_operator(expr: Expression, unop: ast::UnOp) -> Expression {
|
||||
match unop {
|
||||
ast::UnOp::Not(_) => {
|
||||
if let Expression::Boolean(e) = expr {
|
||||
Expression::Boolean(!e)
|
||||
} else {
|
||||
panic!("Unary Not applied to non Number")
|
||||
if let ExpressionType::Boolean(e) = expr.t {
|
||||
return Expression {
|
||||
t: ExpressionType::Boolean(!e),
|
||||
}
|
||||
}
|
||||
}
|
||||
ast::UnOp::Minus(_) => {
|
||||
if let Expression::Number(e) = expr {
|
||||
Expression::Number(-e)
|
||||
} else {
|
||||
panic!("Unary Minus applied to non Number")
|
||||
if let ExpressionType::Number(e) = expr.t {
|
||||
return Expression {
|
||||
t: ExpressionType::Number(-e),
|
||||
}
|
||||
}
|
||||
}
|
||||
ast::UnOp::Hash(_) => {
|
||||
@ -362,4 +446,8 @@ fn apply_unary_operator(expr: Expression, unop: ast::UnOp) -> Expression {
|
||||
}
|
||||
_ => unreachable!()
|
||||
}
|
||||
|
||||
Expression {
|
||||
t: ExpressionType::UnOp(Box::new(expr), UnOp::from(unop)),
|
||||
}
|
||||
}
|
||||
|
@ -1,3 +1,15 @@
|
||||
local L1_1, L1_2
|
||||
local L1_1, L1_2, L41_1, L42_1, L43_1, L44_1, L45_1, L46_1, L47_1, L37_1
|
||||
L1_2 = 2
|
||||
L1_1 = 1 + L1_2
|
||||
L1_1 = true
|
||||
L1_2 = false
|
||||
L1_1 = L1_1 and L1_2
|
||||
|
||||
L41_1 = L37_1
|
||||
L42_1 = 20
|
||||
L43_1 = 76
|
||||
L44_1 = 201
|
||||
L45_1 = 132
|
||||
L46_1 = 98
|
||||
L47_1 = 93
|
||||
L41_1 = (L41_1(L42_1, L43_1, L44_1, L45_1, L46_1, L47_1))
|
||||
|
Loading…
Reference in New Issue
Block a user