resolve_expression.rs 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777
  1. // SPDX-License-Identifier: Apache-2.0
  2. use crate::sema::expression::{
  3. arithmetic::{
  4. addition, bitwise_and, bitwise_or, bitwise_xor, divide, equal, incr_decr, modulo, multiply,
  5. not_equal, power, shift_left, shift_right, subtract,
  6. },
  7. assign::{assign_expr, assign_single},
  8. constructor::{constructor_named_args, new},
  9. function_call::{call_expr, named_call_expr},
  10. integers::{bigint_to_expression, coerce, coerce_number, type_bits_and_sign},
  11. literals::{
  12. address_literal, array_literal, hex_literal, hex_number_literal, number_literal,
  13. rational_number_literal, string_literal, unit_literal,
  14. },
  15. member_access::member_access,
  16. subscript::array_subscript,
  17. variable::variable,
  18. {user_defined_operator, ExprContext, ResolveTo},
  19. };
  20. use crate::sema::{
  21. symtable::Symtable,
  22. unused_variable::{check_function_call, check_var_usage_expression, used_variable},
  23. Recurse,
  24. {
  25. ast::{Expression, Namespace, RetrieveType, Type},
  26. diagnostics::Diagnostics,
  27. eval::check_term_for_constant_overflow,
  28. },
  29. };
  30. use num_bigint::BigInt;
  31. use num_traits::Num;
  32. use solang_parser::{diagnostics::Diagnostic, pt, pt::CodeLocation};
  33. /// Resolve a parsed expression into an AST expression. The resolve_to argument is a hint to what
  34. /// type the result should be.
  35. pub fn expression(
  36. expr: &pt::Expression,
  37. context: &ExprContext,
  38. ns: &mut Namespace,
  39. symtable: &mut Symtable,
  40. diagnostics: &mut Diagnostics,
  41. resolve_to: ResolveTo,
  42. ) -> Result<Expression, ()> {
  43. match expr {
  44. pt::Expression::Parenthesis(_, expr) => {
  45. expression(expr, context, ns, symtable, diagnostics, resolve_to)
  46. }
  47. pt::Expression::ArrayLiteral(loc, exprs) => {
  48. let res = array_literal(loc, exprs, context, ns, symtable, diagnostics, resolve_to);
  49. if let Ok(exp) = &res {
  50. used_variable(ns, exp, symtable);
  51. }
  52. res
  53. }
  54. pt::Expression::BoolLiteral(loc, v) => Ok(Expression::BoolLiteral {
  55. loc: *loc,
  56. value: *v,
  57. }),
  58. pt::Expression::StringLiteral(v) => {
  59. Ok(string_literal(v, context.file_no, diagnostics, resolve_to))
  60. }
  61. pt::Expression::HexLiteral(v) => hex_literal(v, diagnostics, resolve_to),
  62. pt::Expression::NumberLiteral(loc, integer, exp, unit) => {
  63. let unit = unit_literal(loc, unit, ns, diagnostics);
  64. number_literal(loc, integer, exp, ns, &unit, diagnostics, resolve_to)
  65. }
  66. pt::Expression::RationalNumberLiteral(loc, integer, fraction, exp, unit) => {
  67. let unit = unit_literal(loc, unit, ns, diagnostics);
  68. rational_number_literal(
  69. loc,
  70. integer,
  71. fraction,
  72. exp,
  73. &unit,
  74. ns,
  75. diagnostics,
  76. resolve_to,
  77. )
  78. }
  79. pt::Expression::HexNumberLiteral(loc, n, unit) => {
  80. if unit.is_some() {
  81. diagnostics.push(Diagnostic::error(
  82. *loc,
  83. "hexadecimal numbers cannot be used with unit denominations".into(),
  84. ));
  85. }
  86. hex_number_literal(loc, n, ns, diagnostics, resolve_to)
  87. }
  88. pt::Expression::AddressLiteral(loc, address) => {
  89. address_literal(loc, address, ns, diagnostics)
  90. }
  91. pt::Expression::Variable(id) => {
  92. variable(id, context, ns, symtable, diagnostics, resolve_to)
  93. }
  94. pt::Expression::Add(loc, l, r) => {
  95. addition(loc, l, r, context, ns, symtable, diagnostics, resolve_to)
  96. }
  97. pt::Expression::Subtract(loc, l, r) => {
  98. subtract(loc, l, r, context, ns, symtable, diagnostics, resolve_to)
  99. }
  100. pt::Expression::BitwiseOr(loc, l, r) => {
  101. bitwise_or(loc, l, r, context, ns, symtable, diagnostics, resolve_to)
  102. }
  103. pt::Expression::BitwiseAnd(loc, l, r) => {
  104. bitwise_and(loc, l, r, context, ns, symtable, diagnostics, resolve_to)
  105. }
  106. pt::Expression::BitwiseXor(loc, l, r) => {
  107. bitwise_xor(loc, l, r, context, ns, symtable, diagnostics, resolve_to)
  108. }
  109. pt::Expression::ShiftLeft(loc, l, r) => {
  110. shift_left(loc, l, r, context, ns, symtable, diagnostics, resolve_to)
  111. }
  112. pt::Expression::ShiftRight(loc, l, r) => {
  113. shift_right(loc, l, r, context, ns, symtable, diagnostics, resolve_to)
  114. }
  115. pt::Expression::Multiply(loc, l, r) => {
  116. multiply(loc, l, r, context, ns, symtable, diagnostics, resolve_to)
  117. }
  118. pt::Expression::Divide(loc, l, r) => {
  119. divide(loc, l, r, context, ns, symtable, diagnostics, resolve_to)
  120. }
  121. pt::Expression::Modulo(loc, l, r) => {
  122. modulo(loc, l, r, context, ns, symtable, diagnostics, resolve_to)
  123. }
  124. pt::Expression::Power(loc, b, e) => {
  125. power(loc, b, e, context, ns, symtable, diagnostics, resolve_to)
  126. }
  127. // compare
  128. pt::Expression::More(loc, left, right) => {
  129. more(left, right, context, ns, symtable, diagnostics, loc)
  130. }
  131. pt::Expression::Less(loc, left, right) => {
  132. less(left, right, context, ns, symtable, diagnostics, loc)
  133. }
  134. pt::Expression::MoreEqual(loc, left, right) => {
  135. more_equal(left, right, context, ns, symtable, diagnostics, loc)
  136. }
  137. pt::Expression::LessEqual(loc, left, right) => {
  138. less_equal(left, right, context, ns, symtable, diagnostics, loc)
  139. }
  140. pt::Expression::Equal(loc, l, r) => equal(loc, l, r, context, ns, symtable, diagnostics),
  141. pt::Expression::NotEqual(loc, l, r) => {
  142. not_equal(loc, l, r, context, ns, symtable, diagnostics)
  143. }
  144. // unary expressions
  145. pt::Expression::Not(loc, e) => {
  146. let expr = expression(e, context, ns, symtable, diagnostics, resolve_to)?;
  147. used_variable(ns, &expr, symtable);
  148. Ok(Expression::Not {
  149. loc: *loc,
  150. expr: Box::new(expr.cast(loc, &Type::Bool, true, ns, diagnostics)?),
  151. })
  152. }
  153. pt::Expression::BitwiseNot(loc, e) => {
  154. bitwise_not(e, context, ns, symtable, diagnostics, resolve_to, loc)
  155. }
  156. pt::Expression::Negate(loc, e) => {
  157. negate(e, loc, ns, diagnostics, resolve_to, context, symtable)
  158. }
  159. pt::Expression::UnaryPlus(loc, e) => {
  160. let expr = expression(e, context, ns, symtable, diagnostics, resolve_to)?;
  161. used_variable(ns, &expr, symtable);
  162. let expr_type = expr.ty();
  163. type_bits_and_sign(&expr_type, loc, false, ns, diagnostics)?;
  164. diagnostics.push(Diagnostic::error(
  165. *loc,
  166. "unary plus not permitted".to_string(),
  167. ));
  168. Ok(expr)
  169. }
  170. pt::Expression::ConditionalOperator(loc, c, l, r) => {
  171. let left = expression(l, context, ns, symtable, diagnostics, resolve_to)?;
  172. let right = expression(r, context, ns, symtable, diagnostics, resolve_to)?;
  173. check_var_usage_expression(ns, &left, &right, symtable);
  174. let cond = expression(c, context, ns, symtable, diagnostics, resolve_to)?;
  175. used_variable(ns, &cond, symtable);
  176. let cond = cond.cast(&c.loc(), &Type::Bool, true, ns, diagnostics)?;
  177. let ty = coerce(&left.ty(), &l.loc(), &right.ty(), &r.loc(), ns, diagnostics)?;
  178. let left = left.cast(&l.loc(), &ty, true, ns, diagnostics)?;
  179. let right = right.cast(&r.loc(), &ty, true, ns, diagnostics)?;
  180. Ok(Expression::ConditionalOperator {
  181. loc: *loc,
  182. ty,
  183. cond: Box::new(cond),
  184. true_option: Box::new(left),
  185. false_option: Box::new(right),
  186. })
  187. }
  188. // pre/post decrement/increment
  189. pt::Expression::PostIncrement(loc, var)
  190. | pt::Expression::PreIncrement(loc, var)
  191. | pt::Expression::PostDecrement(loc, var)
  192. | pt::Expression::PreDecrement(loc, var) => {
  193. if context.constant {
  194. diagnostics.push(Diagnostic::error(
  195. *loc,
  196. "operator not allowed in constant context".to_string(),
  197. ));
  198. return Err(());
  199. };
  200. incr_decr(var, expr, context, ns, symtable, diagnostics)
  201. }
  202. // assignment
  203. pt::Expression::Assign(loc, var, e) => {
  204. if context.constant {
  205. diagnostics.push(Diagnostic::error(
  206. *loc,
  207. "assignment not allowed in constant context".to_string(),
  208. ));
  209. return Err(());
  210. };
  211. assign_single(loc, var, e, context, ns, symtable, diagnostics)
  212. }
  213. pt::Expression::AssignAdd(loc, var, e)
  214. | pt::Expression::AssignSubtract(loc, var, e)
  215. | pt::Expression::AssignMultiply(loc, var, e)
  216. | pt::Expression::AssignDivide(loc, var, e)
  217. | pt::Expression::AssignModulo(loc, var, e)
  218. | pt::Expression::AssignOr(loc, var, e)
  219. | pt::Expression::AssignAnd(loc, var, e)
  220. | pt::Expression::AssignXor(loc, var, e)
  221. | pt::Expression::AssignShiftLeft(loc, var, e)
  222. | pt::Expression::AssignShiftRight(loc, var, e) => {
  223. if context.constant {
  224. diagnostics.push(Diagnostic::error(
  225. *loc,
  226. "assignment not allowed in constant context".to_string(),
  227. ));
  228. return Err(());
  229. };
  230. let expr = assign_expr(loc, var, expr, e, context, ns, symtable, diagnostics);
  231. if let Ok(expression) = &expr {
  232. expression.recurse(ns, check_term_for_constant_overflow);
  233. }
  234. expr
  235. }
  236. pt::Expression::NamedFunctionCall(loc, ty, args) => named_call_expr(
  237. loc,
  238. ty,
  239. args,
  240. false,
  241. context,
  242. ns,
  243. symtable,
  244. diagnostics,
  245. resolve_to,
  246. ),
  247. pt::Expression::New(loc, call) => {
  248. if context.constant {
  249. diagnostics.push(Diagnostic::error(
  250. expr.loc(),
  251. "new not allowed in constant expression".to_string(),
  252. ));
  253. return Err(());
  254. }
  255. match call.remove_parenthesis() {
  256. pt::Expression::FunctionCall(_, ty, args) => {
  257. let res = new(loc, ty, args, context, ns, symtable, diagnostics);
  258. if let Ok(exp) = &res {
  259. check_function_call(ns, exp, symtable);
  260. }
  261. res
  262. }
  263. pt::Expression::NamedFunctionCall(_, ty, args) => {
  264. let res =
  265. constructor_named_args(loc, ty, args, context, ns, symtable, diagnostics);
  266. if let Ok(exp) = &res {
  267. check_function_call(ns, exp, symtable);
  268. }
  269. res
  270. }
  271. pt::Expression::Variable(id) => {
  272. diagnostics.push(Diagnostic::error(
  273. *loc,
  274. format!("missing constructor arguments to {}", id.name),
  275. ));
  276. Err(())
  277. }
  278. expr => {
  279. diagnostics.push(Diagnostic::error(
  280. expr.loc(),
  281. "type with arguments expected".into(),
  282. ));
  283. Err(())
  284. }
  285. }
  286. }
  287. pt::Expression::Delete(loc, _) => {
  288. diagnostics.push(Diagnostic::error(
  289. *loc,
  290. "delete not allowed in expression".to_string(),
  291. ));
  292. Err(())
  293. }
  294. pt::Expression::FunctionCall(loc, ty, args) => call_expr(
  295. loc,
  296. ty,
  297. args,
  298. false,
  299. context,
  300. ns,
  301. symtable,
  302. diagnostics,
  303. resolve_to,
  304. ),
  305. pt::Expression::ArraySubscript(loc, _, None) => {
  306. diagnostics.push(Diagnostic::error(
  307. *loc,
  308. "expected expression before ']' token".to_string(),
  309. ));
  310. Err(())
  311. }
  312. pt::Expression::ArraySlice(loc, ..) => {
  313. diagnostics.push(Diagnostic::error(
  314. *loc,
  315. "slice not supported yet".to_string(),
  316. ));
  317. Err(())
  318. }
  319. pt::Expression::ArraySubscript(loc, array, Some(index)) => {
  320. array_subscript(loc, array, index, context, ns, symtable, diagnostics)
  321. }
  322. pt::Expression::MemberAccess(loc, e, id) => member_access(
  323. loc,
  324. e.remove_parenthesis(),
  325. id,
  326. context,
  327. ns,
  328. symtable,
  329. diagnostics,
  330. resolve_to,
  331. ),
  332. pt::Expression::Or(loc, left, right) => {
  333. let boolty = Type::Bool;
  334. let l = expression(
  335. left,
  336. context,
  337. ns,
  338. symtable,
  339. diagnostics,
  340. ResolveTo::Type(&boolty),
  341. )?
  342. .cast(loc, &boolty, true, ns, diagnostics)?;
  343. let r = expression(
  344. right,
  345. context,
  346. ns,
  347. symtable,
  348. diagnostics,
  349. ResolveTo::Type(&boolty),
  350. )?
  351. .cast(loc, &boolty, true, ns, diagnostics)?;
  352. check_var_usage_expression(ns, &l, &r, symtable);
  353. Ok(Expression::Or {
  354. loc: *loc,
  355. left: Box::new(l),
  356. right: Box::new(r),
  357. })
  358. }
  359. pt::Expression::And(loc, left, right) => {
  360. let boolty = Type::Bool;
  361. let l = expression(
  362. left,
  363. context,
  364. ns,
  365. symtable,
  366. diagnostics,
  367. ResolveTo::Type(&boolty),
  368. )?
  369. .cast(loc, &boolty, true, ns, diagnostics)?;
  370. let r = expression(
  371. right,
  372. context,
  373. ns,
  374. symtable,
  375. diagnostics,
  376. ResolveTo::Type(&boolty),
  377. )?
  378. .cast(loc, &boolty, true, ns, diagnostics)?;
  379. check_var_usage_expression(ns, &l, &r, symtable);
  380. Ok(Expression::And {
  381. loc: *loc,
  382. left: Box::new(l),
  383. right: Box::new(r),
  384. })
  385. }
  386. pt::Expression::Type(loc, _) => {
  387. diagnostics.push(Diagnostic::error(*loc, "type not expected".to_owned()));
  388. Err(())
  389. }
  390. pt::Expression::List(loc, _) => {
  391. diagnostics.push(Diagnostic::error(
  392. *loc,
  393. "lists only permitted in destructure statements".to_owned(),
  394. ));
  395. Err(())
  396. }
  397. pt::Expression::FunctionCallBlock(loc, ..) => {
  398. diagnostics.push(Diagnostic::error(
  399. *loc,
  400. "unexpect block encountered".to_owned(),
  401. ));
  402. Err(())
  403. }
  404. }
  405. }
  406. fn bitwise_not(
  407. expr: &pt::Expression,
  408. context: &ExprContext,
  409. ns: &mut Namespace,
  410. symtable: &mut Symtable,
  411. diagnostics: &mut Diagnostics,
  412. resolve_to: ResolveTo,
  413. loc: &pt::Loc,
  414. ) -> Result<Expression, ()> {
  415. let expr = expression(expr, context, ns, symtable, diagnostics, resolve_to)?;
  416. used_variable(ns, &expr, symtable);
  417. if let Some(expr) = user_defined_operator(
  418. loc,
  419. &[&expr],
  420. pt::UserDefinedOperator::BitwiseNot,
  421. diagnostics,
  422. ns,
  423. ) {
  424. return Ok(expr);
  425. }
  426. let expr_ty = expr.ty();
  427. // Ensure that the argument is an integer or fixed bytes type
  428. type_bits_and_sign(&expr_ty, loc, true, ns, diagnostics)?;
  429. Ok(Expression::BitwiseNot {
  430. loc: *loc,
  431. ty: expr_ty,
  432. expr: Box::new(expr),
  433. })
  434. }
  435. fn negate(
  436. expr: &pt::Expression,
  437. loc: &pt::Loc,
  438. ns: &mut Namespace,
  439. diagnostics: &mut Diagnostics,
  440. resolve_to: ResolveTo,
  441. context: &ExprContext,
  442. symtable: &mut Symtable,
  443. ) -> Result<Expression, ()> {
  444. match expr {
  445. pt::Expression::NumberLiteral(_, integer, exp, unit) => {
  446. let unit = unit_literal(loc, unit, ns, diagnostics);
  447. number_literal(loc, integer, exp, ns, &-unit, diagnostics, resolve_to)
  448. }
  449. pt::Expression::HexNumberLiteral(_, v, unit) => {
  450. if unit.is_some() {
  451. diagnostics.push(Diagnostic::error(
  452. *loc,
  453. "hexadecimal numbers cannot be used with unit denominations".into(),
  454. ));
  455. }
  456. // a hex literal with a minus before it cannot be an address literal or a bytesN value
  457. let s: String = v.chars().skip(2).filter(|v| *v != '_').collect();
  458. let n = BigInt::from_str_radix(&s, 16).unwrap();
  459. bigint_to_expression(loc, &-n, ns, diagnostics, resolve_to, Some(s.len()))
  460. }
  461. pt::Expression::RationalNumberLiteral(loc, integer, fraction, exp, unit) => {
  462. let unit = unit_literal(loc, unit, ns, diagnostics);
  463. rational_number_literal(
  464. loc,
  465. integer,
  466. fraction,
  467. exp,
  468. &-unit,
  469. ns,
  470. diagnostics,
  471. resolve_to,
  472. )
  473. }
  474. e => {
  475. let expr = expression(e, context, ns, symtable, diagnostics, resolve_to)?;
  476. used_variable(ns, &expr, symtable);
  477. if let Some(expr) = user_defined_operator(
  478. loc,
  479. &[&expr],
  480. pt::UserDefinedOperator::Negate,
  481. diagnostics,
  482. ns,
  483. ) {
  484. return Ok(expr);
  485. }
  486. let expr_type = expr.ty();
  487. if let Expression::NumberLiteral { value, .. } = expr {
  488. bigint_to_expression(loc, &-value, ns, diagnostics, resolve_to, None)
  489. } else if let Expression::RationalNumberLiteral { ty, value: r, .. } = expr {
  490. Ok(Expression::RationalNumberLiteral {
  491. loc: *loc,
  492. ty,
  493. value: -r,
  494. })
  495. } else {
  496. type_bits_and_sign(&expr_type, loc, false, ns, diagnostics)?;
  497. if !expr_type.is_signed_int(ns) {
  498. diagnostics.push(Diagnostic::error(
  499. *loc,
  500. "negate not allowed on unsigned".to_string(),
  501. ));
  502. }
  503. Ok(Expression::Negate {
  504. loc: *loc,
  505. ty: expr_type,
  506. unchecked: context.unchecked,
  507. expr: Box::new(expr),
  508. })
  509. }
  510. }
  511. }
  512. }
  513. fn less_equal(
  514. l: &pt::Expression,
  515. r: &pt::Expression,
  516. context: &ExprContext,
  517. ns: &mut Namespace,
  518. symtable: &mut Symtable,
  519. diagnostics: &mut Diagnostics,
  520. loc: &pt::Loc,
  521. ) -> Result<Expression, ()> {
  522. let left = expression(l, context, ns, symtable, diagnostics, ResolveTo::Integer)?;
  523. let right = expression(r, context, ns, symtable, diagnostics, ResolveTo::Integer)?;
  524. check_var_usage_expression(ns, &left, &right, symtable);
  525. if let Some(expr) = user_defined_operator(
  526. loc,
  527. &[&left, &right],
  528. pt::UserDefinedOperator::LessEqual,
  529. diagnostics,
  530. ns,
  531. ) {
  532. return Ok(expr);
  533. }
  534. let ty = coerce_number(
  535. &left.ty(),
  536. &l.loc(),
  537. &right.ty(),
  538. &r.loc(),
  539. true,
  540. true,
  541. ns,
  542. diagnostics,
  543. )?;
  544. if ty.is_rational() {
  545. diagnostics.push(Diagnostic::error(
  546. *loc,
  547. "cannot use rational numbers with '<=' operator".into(),
  548. ));
  549. return Err(());
  550. }
  551. let left = expression(l, context, ns, symtable, diagnostics, ResolveTo::Type(&ty))?;
  552. let right = expression(r, context, ns, symtable, diagnostics, ResolveTo::Type(&ty))?;
  553. let expr = Expression::LessEqual {
  554. loc: *loc,
  555. left: Box::new(left.cast(&l.loc(), &ty, true, ns, diagnostics)?),
  556. right: Box::new(right.cast(&r.loc(), &ty, true, ns, diagnostics)?),
  557. };
  558. Ok(expr)
  559. }
  560. fn more_equal(
  561. l: &pt::Expression,
  562. r: &pt::Expression,
  563. context: &ExprContext,
  564. ns: &mut Namespace,
  565. symtable: &mut Symtable,
  566. diagnostics: &mut Diagnostics,
  567. loc: &pt::Loc,
  568. ) -> Result<Expression, ()> {
  569. let left = expression(l, context, ns, symtable, diagnostics, ResolveTo::Integer)?;
  570. let right = expression(r, context, ns, symtable, diagnostics, ResolveTo::Integer)?;
  571. check_var_usage_expression(ns, &left, &right, symtable);
  572. if let Some(expr) = user_defined_operator(
  573. loc,
  574. &[&left, &right],
  575. pt::UserDefinedOperator::MoreEqual,
  576. diagnostics,
  577. ns,
  578. ) {
  579. return Ok(expr);
  580. }
  581. let ty = coerce_number(
  582. &left.ty(),
  583. &l.loc(),
  584. &right.ty(),
  585. &r.loc(),
  586. true,
  587. true,
  588. ns,
  589. diagnostics,
  590. )?;
  591. if ty.is_rational() {
  592. diagnostics.push(Diagnostic::error(
  593. *loc,
  594. "cannot use rational numbers with '>=' operator".into(),
  595. ));
  596. return Err(());
  597. }
  598. let left = expression(l, context, ns, symtable, diagnostics, ResolveTo::Type(&ty))?;
  599. let right = expression(r, context, ns, symtable, diagnostics, ResolveTo::Type(&ty))?;
  600. let expr = Expression::MoreEqual {
  601. loc: *loc,
  602. left: Box::new(left.cast(&l.loc(), &ty, true, ns, diagnostics)?),
  603. right: Box::new(right.cast(&r.loc(), &ty, true, ns, diagnostics)?),
  604. };
  605. Ok(expr)
  606. }
  607. fn less(
  608. l: &pt::Expression,
  609. r: &pt::Expression,
  610. context: &ExprContext,
  611. ns: &mut Namespace,
  612. symtable: &mut Symtable,
  613. diagnostics: &mut Diagnostics,
  614. loc: &pt::Loc,
  615. ) -> Result<Expression, ()> {
  616. let left = expression(l, context, ns, symtable, diagnostics, ResolveTo::Integer)?;
  617. let right = expression(r, context, ns, symtable, diagnostics, ResolveTo::Integer)?;
  618. check_var_usage_expression(ns, &left, &right, symtable);
  619. if let Some(expr) = user_defined_operator(
  620. loc,
  621. &[&left, &right],
  622. pt::UserDefinedOperator::Less,
  623. diagnostics,
  624. ns,
  625. ) {
  626. return Ok(expr);
  627. }
  628. let ty = coerce_number(
  629. &left.ty(),
  630. &l.loc(),
  631. &right.ty(),
  632. &r.loc(),
  633. true,
  634. true,
  635. ns,
  636. diagnostics,
  637. )?;
  638. if ty.is_rational() {
  639. diagnostics.push(Diagnostic::error(
  640. *loc,
  641. "cannot use rational numbers with '<' operator".into(),
  642. ));
  643. return Err(());
  644. }
  645. let left = expression(l, context, ns, symtable, diagnostics, ResolveTo::Type(&ty))?;
  646. let right = expression(r, context, ns, symtable, diagnostics, ResolveTo::Type(&ty))?;
  647. let expr = Expression::Less {
  648. loc: *loc,
  649. left: Box::new(left.cast(&l.loc(), &ty, true, ns, diagnostics)?),
  650. right: Box::new(right.cast(&r.loc(), &ty, true, ns, diagnostics)?),
  651. };
  652. Ok(expr)
  653. }
  654. fn more(
  655. l: &pt::Expression,
  656. r: &pt::Expression,
  657. context: &ExprContext,
  658. ns: &mut Namespace,
  659. symtable: &mut Symtable,
  660. diagnostics: &mut Diagnostics,
  661. loc: &pt::Loc,
  662. ) -> Result<Expression, ()> {
  663. let left = expression(l, context, ns, symtable, diagnostics, ResolveTo::Integer)?;
  664. let right = expression(r, context, ns, symtable, diagnostics, ResolveTo::Integer)?;
  665. check_var_usage_expression(ns, &left, &right, symtable);
  666. if let Some(expr) = user_defined_operator(
  667. loc,
  668. &[&left, &right],
  669. pt::UserDefinedOperator::More,
  670. diagnostics,
  671. ns,
  672. ) {
  673. return Ok(expr);
  674. }
  675. let ty = coerce_number(
  676. &left.ty(),
  677. &l.loc(),
  678. &right.ty(),
  679. &r.loc(),
  680. true,
  681. true,
  682. ns,
  683. diagnostics,
  684. )?;
  685. if ty.is_rational() {
  686. diagnostics.push(Diagnostic::error(
  687. *loc,
  688. "cannot use rational numbers with '>' operator".into(),
  689. ));
  690. return Err(());
  691. }
  692. let left = expression(l, context, ns, symtable, diagnostics, ResolveTo::Type(&ty))?;
  693. let right = expression(r, context, ns, symtable, diagnostics, ResolveTo::Type(&ty))?;
  694. let expr = Expression::More {
  695. loc: *loc,
  696. left: Box::new(left.cast(&l.loc(), &ty, true, ns, diagnostics)?),
  697. right: Box::new(right.cast(&r.loc(), &ty, true, ns, diagnostics)?),
  698. };
  699. Ok(expr)
  700. }