-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.go
126 lines (108 loc) · 2.82 KB
/
main.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
package main
import (
"bufio"
"flag"
"fmt"
"io/ioutil"
"os"
"github.com/nekketsuuu/lambda2pi/lib/convert"
)
func usage() {
fmt.Fprintf(os.Stderr, "[Description of %s]\n", os.Args[0])
fmt.Fprintf(os.Stderr, `This program converts a lambda term into a pi term.
Precise syntax are described under the description of options.
[Options]
`)
flag.PrintDefaults()
fmt.Fprintf(os.Stderr, `
[Syntax]
The syntax of the lambda calculus:
M ::= x // variables
| \x. x // lambda abstraction
| M M // application
| (M) // parenthesis
Note that a period is required in each lambda abstraction. The period means the longest match rule of the abstraction. Therefore, (\x. y \z. w) means (\x. (y (\z. w))), not ((\x. y) (\z. w)).
The syntax of the pi calculus:
M ::= O // the empty process
// (Note that the symbol is not zero,
// but the 15th latin alphabet, O.)
| x // names
| x?x.M // input
| x!x.M // output
| M|M // parallel execution
| *M // replication (*M is congruent to M|*M)
| new x in M // name restriction
| (M) // parenthesis
Note that there is no summation.
`)
}
var (
showVersion bool
inputFile string
outputFile string
evalModeString string
)
func setFlags() {
flag.Usage = usage
flag.BoolVar(&showVersion, "version", false, "show version")
flag.BoolVar(&showVersion, "v", false, "show version")
flag.StringVar(&outputFile, "o", "out.pi", "an output filename")
flag.StringVar(&evalModeString, "mode", "CallByValue", "an evaluation strategy for the lambda calculus (value: CallByValue, CallByName)")
flag.Parse()
inputFile = flag.Arg(0)
}
func main() {
setFlags()
if err := Run(); err != nil {
fmt.Fprintf(os.Stderr, "[ERROR] lambda2pi: %v\n", err)
}
}
func Run() error {
if showVersion {
fmt.Println("lambda2pi", version)
} else {
mode, err := convert.ToMode(evalModeString)
if err != nil {
return err
}
if inputFile != "" {
return fileMode(mode)
} else {
return replMode(mode)
}
}
return nil
}
func fileMode(mode convert.EvalMode) error {
pi, err := convert.ConvertFromFile(inputFile, mode)
if err != nil {
return err
}
str := fmt.Sprintln(pi.String())
err = ioutil.WriteFile(outputFile, []byte(str), 0664)
if err != nil {
return err
}
return nil
}
func replMode(mode convert.EvalMode) error {
fmt.Println("lambda2pi", version, "REPL mode")
scanner := bufio.NewScanner(os.Stdin)
REPL:
for {
fmt.Printf(">> ")
if !scanner.Scan() {
break REPL
}
p, err := convert.ConvertFromString(scanner.Text(), mode)
if err != nil {
fmt.Fprintln(os.Stderr, "[ERROR]", err)
} else {
fmt.Println(p.String())
}
}
if err := scanner.Err(); err != nil {
return err
}
return nil
}