diff options
author | Piotr Fusik <piotr@fusion-lang.org> | 2024-02-28 20:46:10 +0100 |
---|---|---|
committer | Piotr Fusik <piotr@fusion-lang.org> | 2024-02-28 20:46:10 +0100 |
commit | f9cbcd86f92e383796ad37543996dc87c1f788cc (patch) | |
tree | 92feecbf6239fec3bfd9e31e92be7935a03a359b | |
parent | fdadd2203c27f37028fc9a69d1bee8ff6b785661 (diff) |
[java] if (!number.TryParse(str)).
#140
-rw-r--r-- | GenJava.fu | 41 | ||||
-rw-r--r-- | libfut.cpp | 44 | ||||
-rw-r--r-- | libfut.cs | 39 | ||||
-rw-r--r-- | libfut.hpp | 2 | ||||
-rw-r--r-- | libfut.js | 44 |
5 files changed, 170 insertions, 0 deletions
@@ -1101,6 +1101,47 @@ public class GenJava : GenTyped WriteChild(statement.Body); } + static bool IsTryParse(FuId id) => id == FuId.IntTryParse || id == FuId.LongTryParse || id == FuId.DoubleTryParse; + + internal override void VisitIf!(FuIf statement) + { + if (statement.OnFalse == null + && statement.Cond is FuPrefixExpr not && not.Op == FuToken.ExclamationMark + && not.Inner is FuCallExpr call && IsTryParse(call.Method.Symbol.Id)) { + Write("try "); + OpenBlock(); + call.Method.Left.Accept(this, FuPriority.Assign); + Write(" = "); + switch (call.Method.Symbol.Id) { + case FuId.IntTryParse: + Write("Integer.parseInt"); + break; + case FuId.LongTryParse: + Write("Long.parseLong"); + break; + case FuId.DoubleTryParse: + Write("Double.parseDouble"); + break; + default: + assert false; + } + WriteChar('('); + call.Arguments[0].Accept(this, FuPriority.Argument); + if (call.Arguments.Count == 2) { + Write(", "); + call.Arguments[1].Accept(this, FuPriority.Argument); + } + WriteLine(");"); + CloseBlock(); + Write("catch (NumberFormatException e) "); + OpenBlock(); + statement.OnTrue.AcceptStatement(this); + CloseBlock(); + } + else + base.VisitIf(statement); + } + internal override void VisitLock!(FuLock statement) { WriteCall("synchronized ", statement.Lock); @@ -18441,6 +18441,50 @@ void GenJava::visitForeach(const FuForeach * statement) writeChild(statement->body.get()); } +bool GenJava::isTryParse(FuId id) +{ + return id == FuId::intTryParse || id == FuId::longTryParse || id == FuId::doubleTryParse; +} + +void GenJava::visitIf(const FuIf * statement) +{ + const FuPrefixExpr * not_; + const FuCallExpr * call; + if (statement->onFalse == nullptr && (not_ = dynamic_cast<const FuPrefixExpr *>(statement->cond.get())) && not_->op == FuToken::exclamationMark && (call = dynamic_cast<const FuCallExpr *>(not_->inner.get())) && isTryParse(call->method->symbol->id)) { + write("try "); + openBlock(); + call->method->left->accept(this, FuPriority::assign); + write(" = "); + switch (call->method->symbol->id) { + case FuId::intTryParse: + write("Integer.parseInt"); + break; + case FuId::longTryParse: + write("Long.parseLong"); + break; + case FuId::doubleTryParse: + write("Double.parseDouble"); + break; + default: + std::abort(); + } + writeChar('('); + call->arguments[0]->accept(this, FuPriority::argument); + if (std::ssize(call->arguments) == 2) { + write(", "); + call->arguments[1]->accept(this, FuPriority::argument); + } + writeLine(");"); + closeBlock(); + write("catch (NumberFormatException e) "); + openBlock(); + statement->onTrue->acceptStatement(this); + closeBlock(); + } + else + GenBase::visitIf(statement); +} + void GenJava::visitLock(const FuLock * statement) { writeCall("synchronized ", statement->lock.get()); @@ -19080,6 +19080,45 @@ namespace Fusion WriteChild(statement.Body); } + static bool IsTryParse(FuId id) => id == FuId.IntTryParse || id == FuId.LongTryParse || id == FuId.DoubleTryParse; + + internal override void VisitIf(FuIf statement) + { + if (statement.OnFalse == null && statement.Cond is FuPrefixExpr not && not.Op == FuToken.ExclamationMark && not.Inner is FuCallExpr call && IsTryParse(call.Method.Symbol.Id)) { + Write("try "); + OpenBlock(); + call.Method.Left.Accept(this, FuPriority.Assign); + Write(" = "); + switch (call.Method.Symbol.Id) { + case FuId.IntTryParse: + Write("Integer.parseInt"); + break; + case FuId.LongTryParse: + Write("Long.parseLong"); + break; + case FuId.DoubleTryParse: + Write("Double.parseDouble"); + break; + default: + throw new NotImplementedException(); + } + WriteChar('('); + call.Arguments[0].Accept(this, FuPriority.Argument); + if (call.Arguments.Count == 2) { + Write(", "); + call.Arguments[1].Accept(this, FuPriority.Argument); + } + WriteLine(");"); + CloseBlock(); + Write("catch (NumberFormatException e) "); + OpenBlock(); + statement.OnTrue.AcceptStatement(this); + CloseBlock(); + } + else + base.VisitIf(statement); + } + internal override void VisitLock(FuLock statement) { WriteCall("synchronized ", statement.Lock); @@ -2521,6 +2521,7 @@ public: void visitSymbolReference(const FuSymbolReference * expr, FuPriority parent) override; void visitLambdaExpr(const FuLambdaExpr * expr) override; void visitForeach(const FuForeach * statement) override; + void visitIf(const FuIf * statement) override; void visitLock(const FuLock * statement) override; void visitReturn(const FuReturn * statement) override; void visitSwitch(const FuSwitch * statement) override; @@ -2540,6 +2541,7 @@ private: void writeArrayBinarySearchFill(const FuExpr * obj, std::string_view method, const std::vector<std::shared_ptr<FuExpr>> * args); void writeWrite(const FuMethod * method, const std::vector<std::shared_ptr<FuExpr>> * args, bool newLine); void writeCompileRegex(const std::vector<std::shared_ptr<FuExpr>> * args, int argIndex); + static bool isTryParse(FuId id); void createJavaFile(std::string_view className); void writeSignature(const FuMethod * method, int paramCount); void writeOverloads(const FuMethod * method, int paramCount); @@ -19612,6 +19612,50 @@ export class GenJava extends GenTyped this.writeChild(statement.body); } + static #isTryParse(id) + { + return id == FuId.INT_TRY_PARSE || id == FuId.LONG_TRY_PARSE || id == FuId.DOUBLE_TRY_PARSE; + } + + visitIf(statement) + { + let not; + let call; + if (statement.onFalse == null && (not = statement.cond) instanceof FuPrefixExpr && not.op == FuToken.EXCLAMATION_MARK && (call = not.inner) instanceof FuCallExpr && GenJava.#isTryParse(call.method.symbol.id)) { + this.write("try "); + this.openBlock(); + call.method.left.accept(this, FuPriority.ASSIGN); + this.write(" = "); + switch (call.method.symbol.id) { + case FuId.INT_TRY_PARSE: + this.write("Integer.parseInt"); + break; + case FuId.LONG_TRY_PARSE: + this.write("Long.parseLong"); + break; + case FuId.DOUBLE_TRY_PARSE: + this.write("Double.parseDouble"); + break; + default: + throw new Error(); + } + this.writeChar(40); + call.arguments_[0].accept(this, FuPriority.ARGUMENT); + if (call.arguments_.length == 2) { + this.write(", "); + call.arguments_[1].accept(this, FuPriority.ARGUMENT); + } + this.writeLine(");"); + this.closeBlock(); + this.write("catch (NumberFormatException e) "); + this.openBlock(); + statement.onTrue.acceptStatement(this); + this.closeBlock(); + } + else + super.visitIf(statement); + } + visitLock(statement) { this.writeCall("synchronized ", statement.lock); |