This repository has been archived by the owner on Apr 5, 2024. It is now read-only.
forked from ocen-lang/ocen
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.oc
142 lines (123 loc) · 4.07 KB
/
main.oc
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
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
//* Entry point for the compiler
import std::libc::{ exit, calloc, system }
import .ast::program::Program
import .parser::Parser
import .passes::{ run_typecheck_passes, run_codegen_passes }
import .docgen::generate_doc_json
def usage(code: i32) {
println("--------------------------------------------------------")
println("Usage: ./ocen [options] <file>")
println("Options:")
println(" -o path Output executable (default: ./out)")
println(" -c path Output C code (default: {out}.c)")
println(" -e0 Minimal one-line errors")
println(" -e1 Error messages with source code (default)")
println(" -e2 Error messages with source / hints")
println(" -s Silent mode (no debug output)")
println(" -n Don't compile C code (default: false)")
println(" -d Emit debug information (default: false)")
println(" -l path Directory to search for libraries (can be used multiple times)")
println(" --docs path Output documentation JSON (default: none)")
println(" (Default: working directory)")
println("--------------------------------------------------------")
exit(code)
}
let exec_path: str = "./out"
let c_path: str = null
let filename: str = null
let compile_c: bool = true
let silent: bool = false
let debug: bool = false
let error_level: u32 = 2
let docs_path: str = null
def save_and_compile_code(program: &Program, code: str) {
if not c_path? {
c_path = `{exec_path}.c`
}
let out_file = std::File::open(c_path, "w")
out_file.puts(code)
out_file.close()
if not compile_c then return
let cmdbuf = calloc(1, 1024) as str
cmdbuf.concat(`gcc -o {exec_path} {c_path}`)
for flag : program.c_flags.iter() {
cmdbuf.concat(" ")
cmdbuf.concat(flag)
}
if debug {
cmdbuf.concat(" -ggdb3")
}
if not silent {
println("[+] %s", cmdbuf)
}
let exit_code = system(cmdbuf)
if exit_code != 0 {
println("[-] Compilation failed")
exit(1)
}
}
def parse_args(argc: i32, argv: &str, program: &Program) {
for let i = 1; i < argc as u32; i += 1 {
match argv[i] {
"-h" => usage(code: 0)
"-s" => silent = true
"-d" => debug = true
"-n" => compile_c = false
"-o" => {
i += 1
exec_path = argv[i]
}
"-c" => {
i += 1
c_path = argv[i]
}
"-l" => {
i += 1
program.library_paths.push(argv[i])
}
"-e0" => error_level = 0
"-e1" => error_level = 1
"-e2" => error_level = 2
"--docs" => {
i += 1
docs_path = argv[i]
program.check_doc_links = true
}
else => {
if argv[i][0] == '-' {
println("Unknown option: %s", argv[i])
usage(1)
} else if not filename? {
filename = argv[i]
} else {
println("Unknown option/argument: '%s'", argv[i])
usage(code: 1)
}
}
}
}
if not filename? {
println("No file specified")
usage(code: 1)
}
}
def main(argc: i32, argv: &str) {
let program = Program::new()
program.library_paths.push("")
let ocen_root = std::libc::getenv("OCEN_ROOT")
if ocen_root? and ocen_root.len() > 0 {
program.library_paths.push(ocen_root)
}
parse_args(argc, argv, program)
program.error_level = error_level
program.gen_debug_info = debug
Parser::parse_toplevel(program, filename)
if not program.errors.is_empty() then program.exit_with_errors()
run_typecheck_passes(program)
if docs_path? {
generate_doc_json(program, docs_path)
} else {
let code = run_codegen_passes(program)
save_and_compile_code(program, code)
}
}