你如何从ATS2中的主函数读入和访问参数?

时间:2018-03-14 22:30:10

标签: ats

这是一项常见的基本任务,因此了解适当的方法是很好的。 C ++中的类似程序可能如下所示(ref):

#include <iostream>
using namespace std;

int main(int argc, char** argv)
{

    for (int i = 0; i < argc; ++i)
        cout << argv[i] << "\n";

    return 0;
}

在此示例中,我们将在命令行上打印出每个参数。因此运行像./main.exe asdf 1234 bob这样的编程会给出:

./main.exe 
asdf 
1234 
bob

3 个答案:

答案 0 :(得分:3)

这与C中的相同类型的程序非常相似,但有一些与约束和线性类型相关的差异。设置后约束很简单:

(*
Run patscc -o hello hello.dats
*)

#include "share/atspre_staload.hats"

implement main0{n}
(argc, argv): void = {

  fun echoArgs{i:nat | i < n}
  (ii: int(i), argv: !argv(n)): void = {
    val () = println!("arg ", ii, " is ", argv[ii])
    val () = if ii + 1 < argc then echoArgs(ii + 1, argv) 
  }

  val () = echoArgs(0, argv)
}

由于我们需要访问argv的内容,我们必须通过提供线性相关类型!argv(n)来更改其viewtype的视图; corresponds中的! linear logic表示在函数调用后该类型的值仍然可用; (n)只表示argv是一个大小为n的字符串数组。我们必须保证数组中的索引i小于数组的大小n

答案 1 :(得分:1)

这是一种基于组合器的风格:

#include "share/atspre_staload.hats"
#include "share/atspre_staload_libats_ML.hats"

implement
main0(argc, argv) = let
//
val args = listize_argc_argv(argc, argv)
//
in
  list0_foreach(args, lam(arg) => println!(arg))
end // end of [main0]

答案 2 :(得分:1)

可能更常见的是从命令行获取标志和参数,以改变程序行为。为此,您可以使用getopt(或稍微复杂但更好的CLI接口,GNU getopt)。这些功能基本上适合你。

有点愚蠢的例子:

#include "share/atspre_staload.hats"
%{^
#include <unistd.h>
%}

extern fun getopt{n:int}(argc: int, argv: !argv(n), flags: string): int = "mac#"

val trad = ref<bool>(false)
val color = ref<bool>(false)
val progname = ref<string>("hello4")

fn get_progname{n:int}(argc: int(n), argv: !argv(n)): void =
        if argc > 0 then
                !progname := argv[0]

implement main0(argc, argv) = (
        get_progname(argc, argv);
        process_args(argc, argv);
        case+ (!trad, !color) of
        | (true, true) => println!("\033[31;1mhello world\033[0m")
        | (true, false) => println!("hello world")
        | (false, true) => println!("\033[31;1mHello, world!\033[0m")
        | (false, false) => println!("Hello, modern world!")
) where {
        fn usage(): void = (
                fprintln!(stderr_ref, "usage: ", !progname, " [-htc]");
                exit(1);
        )
        fun process_args{n:int}(argc: int, argv: !argv(n)): void =
                let
                        val r = getopt(argc, argv, "htc")
                in
                        if r >= 0 then (
                                ifcase
                                | r = 'h' => usage()
                                | r = 't' => (!trad := true; process_args(argc, argv))
                                | r = 'c' => (!color := true; process_args(argc, argv))
                                | _ => (println!("fell through with: ", $UNSAFE.cast{char}(r)); usage())
                        )
                end
}

用法:

$ ./hello4
Hello, modern world!
$ ./hello4 -t
hello world
$ ./hello4 -c
Hello, world!    <-- this is red