From 305a434db05e025e5889f9f34e4a1a6b9717027f Mon Sep 17 00:00:00 2001 From: angelcaru Date: Wed, 1 May 2024 17:08:45 +0200 Subject: [PATCH] Add conversors --- core/interpreter.py | 9 ++++++++- examples/simple-grep.rn | 4 ++-- stdlib/Argparser.rn | 37 +++++++++++++++++++++++++++++++------ 3 files changed, 41 insertions(+), 9 deletions(-) diff --git a/core/interpreter.py b/core/interpreter.py index 27eece0..d3f04d0 100755 --- a/core/interpreter.py +++ b/core/interpreter.py @@ -523,8 +523,15 @@ def visit_ForInNode(self, node: ForInNode, context: Context) -> RTResult[Value]: for it_res in it: element = res.register(it_res) - if res.should_return(): + if res.should_return() and not res.loop_should_continue and not res.loop_should_break: return res + + if res.loop_should_break: + break + + if res.loop_should_continue: + continue + assert element is not None context.symbol_table.set(var_name, element) diff --git a/examples/simple-grep.rn b/examples/simple-grep.rn index 886cfcd..9c8bc41 100644 --- a/examples/simple-grep.rn +++ b/examples/simple-grep.rn @@ -6,7 +6,7 @@ fun main() { parser.add_pos_opt("query", "String to query", required=true) parser.add_pos_opt("file", "File to query string in", required=true) parser.add_flag("--line-numbers", "-n", "Show line numbers") - parser.add_named("--max-lines", "Maximum amount of lines to show") + parser.add_named("--max-lines", "Maximum amount of lines to show", conversor=int) args = parser.parse(argv[:]) if args["--help"] { @@ -28,7 +28,7 @@ fun main() { } if not is_null(args["--max-lines"]) { - nonlocal matched_lines = matched_lines[:int(args["--max-lines"])] + nonlocal matched_lines = matched_lines[:args["--max-lines"]] } for line in matched_lines { diff --git a/stdlib/Argparser.rn b/stdlib/Argparser.rn index 45321b7..d3d7d7b 100755 --- a/stdlib/Argparser.rn +++ b/stdlib/Argparser.rn @@ -25,11 +25,14 @@ class Argparser { this.named = [] } - fun add_pos_opt(name, desc, default_=null, required=false) { + fun add_pos_opt(name, desc, default_=null, required=false, conversor=null) { if required { assert is_null(default_), "Required positional arguments cannot have a default value" } - arr_append(this.pos_opts, {"name": name, "desc": desc, "default": default_, "required": required}) + if is_null(conversor) { + nonlocal conversor = fun(x) -> x + } + arr_append(this.pos_opts, {"name": name, "desc": desc, "default": default_, "required": required, "conversor": conversor}) return this } @@ -41,12 +44,24 @@ class Argparser { return this } - fun add_named(name, desc, default_=null) { + fun add_named(name, desc, default_=null, conversor=null) { assert str_starts_with(name, "--"), "Named arguments must start with '--'" - arr_append(this.named, {"name": name, "desc": desc, "default": default_}) + if is_null(conversor) { + nonlocal conversor = fun(x) -> x + } + arr_append(this.named, {"name": name, "desc": desc, "default": default_, "conversor": conversor}) return this } + fun get_named_conversor(name) { + for named in this.named { + if named["name"] == name { + return named["conversor"] + } + } + return null + } + fun usage(program_name) { ret = "Usage: "+program_name+" \n" ret += "OPTIONS:\n" @@ -124,7 +139,12 @@ class Argparser { this.report_error(program_name, "missing value for flag: '"+arg+"'") } value = arr_pop(args, 0) - parsed[arg] = value + conversor = this.get_named_conversor(arg) + try { + parsed[arg] = conversor(value) + } catch as e { + this.report_error(program_name, "invalid value for flag: "+arg+"': " + str(e)) + } } } } else { @@ -142,7 +162,12 @@ class Argparser { this.report_error(program_name, "unexpected positional argument: '" + arg + "'") } arg_name = pos_opts[pos_opts_idx]["name"] - parsed[arg_name] = arg + conversor = pos_opts[pos_opts_idx]["conversor"] + try { + parsed[arg_name] = conversor(arg) + } catch as e { + this.report_error(program_name, "invalid value for argument: '" + arg_name + "': " + str(e)) + } required_opts[arg_name] = false nonlocal pos_opts_idx++ }