js: codegen fixes, W.I.P `os` availability for JS backend (#11281)
parent
47278b4a7d
commit
d78e7e3b2b
|
@ -239,3 +239,7 @@ pub fn (a array) contains(key voidptr) bool {
|
|||
pub fn (mut a array) delete_last() {
|
||||
#a.val.arr.pop();
|
||||
}
|
||||
|
||||
[unsafe]
|
||||
pub fn (a array) free() {
|
||||
}
|
||||
|
|
|
@ -1,3 +1,7 @@
|
|||
module math
|
||||
|
||||
fn JS.Math.pow(x f64, y f64) f64
|
||||
|
||||
pub fn pow(x f64, y f64) f64 {
|
||||
return JS.Math.pow(x, y)
|
||||
}
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
module os
|
||||
|
||||
$if js_node {
|
||||
#const $ENV = $process.env
|
||||
} $else {
|
||||
#const $ENV = {}
|
||||
}
|
||||
|
||||
// setenv sets the value of an environment variable with `name` to `value`.
|
||||
pub fn setenv(key string, val string, overwrite bool) {
|
||||
#if ($ENV[key] && !(overwrite.valueOf())) return;
|
||||
#$ENV[key] = val + '';
|
||||
}
|
||||
|
||||
// `getenv` returns the value of the environment variable named by the key.
|
||||
pub fn getenv(key string) string {
|
||||
mut res := ''
|
||||
#if ($ENV[key]) res = new builtin.string($ENV[key])
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
// unsetenv clears an environment variable with `name`.
|
||||
pub fn unsetenv(name string) int {
|
||||
#$ENV[name] = ""
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
pub fn environ() map[string]string {
|
||||
mut res := map[string]string{}
|
||||
#for (const key in $ENV) {
|
||||
#res.map.set(key,$ENV[key])
|
||||
#}
|
||||
|
||||
return res
|
||||
}
|
|
@ -0,0 +1,97 @@
|
|||
module os
|
||||
|
||||
#const $fs = require('fs');
|
||||
#const $path = require('path');
|
||||
|
||||
pub const (
|
||||
args = []string{}
|
||||
path_delimiter = '/'
|
||||
path_separator = '/'
|
||||
)
|
||||
|
||||
$if js_node {
|
||||
#$process.argv.forEach(function(val,index) { args.arr[index] = new string(val); })
|
||||
}
|
||||
|
||||
// real_path returns the full absolute path for fpath, with all relative ../../, symlinks and so on resolved.
|
||||
// See http://pubs.opengroup.org/onlinepubs/9699919799/functions/realpath.html
|
||||
// Also https://insanecoding.blogspot.com/2007/11/pathmax-simply-isnt.html
|
||||
// and https://insanecoding.blogspot.com/2007/11/implementing-realpath-in-c.html
|
||||
// NB: this particular rabbit hole is *deep* ...
|
||||
pub fn real_path(fpath string) string {
|
||||
$if js_node {
|
||||
mut res := ''
|
||||
#res = new string( $fs.realpathSync(fpath))
|
||||
|
||||
return res
|
||||
} $else {
|
||||
return fpath
|
||||
}
|
||||
}
|
||||
|
||||
// flush will flush the stdout buffer.
|
||||
pub fn flush() {
|
||||
$if js_node {
|
||||
#$process.stdout.write('')
|
||||
}
|
||||
}
|
||||
|
||||
// chmod change file access attributes of `path` to `mode`.
|
||||
// Octals like `0o600` can be used.
|
||||
pub fn chmod(path string, mode int) {
|
||||
$if js_node {
|
||||
#$fs.chmodSync(''+path,mode.valueOf())
|
||||
}
|
||||
}
|
||||
|
||||
// chown changes the owner and group attributes of `path` to `owner` and `group`.
|
||||
// Octals like `0o600` can be used.
|
||||
pub fn chown(path string, owner int, group int) {
|
||||
$if js_node {
|
||||
#$fs.chownSync(''+path,owner.valueOf(),group.valueOf())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn temp_dir() string {
|
||||
mut res := ''
|
||||
$if js_node {
|
||||
#res = new builtin.string($os.tmpdir())
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
pub fn home_dir() string {
|
||||
mut res := ''
|
||||
$if js_node {
|
||||
#res = new builtin.string($os.homedir())
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
// join_path returns a path as string from input string parameter(s).
|
||||
pub fn join_path(base string, dirs ...string) string {
|
||||
mut result := []string{}
|
||||
result << base.trim_right('\\/')
|
||||
for d in dirs {
|
||||
result << d
|
||||
}
|
||||
mut path_sep := ''
|
||||
#path_sep = $path.sep;
|
||||
|
||||
res := result.join(path_sep)
|
||||
return res
|
||||
}
|
||||
|
||||
pub fn execute(cmd string) Result {
|
||||
mut exit_code := 0
|
||||
mut stdout := ''
|
||||
#let commands = cmd.str.split(' ');
|
||||
#let output = $child_process.spawnSync(commands[0],commands.slice(1,commands.length));
|
||||
#exit_code = new builtin.int(output.status)
|
||||
#stdout = new builtin.string(output.stdout + '')
|
||||
|
||||
return Result{
|
||||
exit_code: exit_code
|
||||
output: stdout
|
||||
}
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
module os
|
||||
|
||||
pub fn mkdir(path string) ?bool {
|
||||
$if js_node {
|
||||
if path == '.' {
|
||||
return true
|
||||
}
|
||||
#$fs.mkdirSync(path.valueOf())
|
||||
|
||||
return true
|
||||
} $else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_dir(path string) bool {
|
||||
res := false
|
||||
#res.val = $fs.existsSync(path,str) && $fs.lstatSync(path.str).isDirectory()
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
pub fn is_link(path string) bool {
|
||||
res := false
|
||||
#res.val = $fs.existsSync(path.str) && $fs.lstatSync(path.str).isSymbolicLink()
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
pub fn exists(path string) bool {
|
||||
res := false
|
||||
#res.val = $fs.existsSync(path.str)
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
pub fn ls(path string) ?[]string {
|
||||
if !is_dir(path) {
|
||||
return error('ls(): cannot open dir $dir')
|
||||
}
|
||||
|
||||
result := []string{}
|
||||
#let i = 0
|
||||
#$fs.readdirSync(path.str).forEach((path) => result.arr[i++] = new builtin.string(path))
|
||||
|
||||
return result
|
||||
}
|
|
@ -0,0 +1,248 @@
|
|||
module os
|
||||
|
||||
// signal_kill - kills the process, after that it is no longer running
|
||||
pub fn (mut p Process) signal_kill() {
|
||||
if p.status !in [.running, .stopped] {
|
||||
return
|
||||
}
|
||||
p._signal_kill()
|
||||
p.status = .aborted
|
||||
return
|
||||
}
|
||||
|
||||
// signal_pgkill - kills the whole process group
|
||||
pub fn (mut p Process) signal_pgkill() {
|
||||
if p.status !in [.running, .stopped] {
|
||||
return
|
||||
}
|
||||
p._signal_pgkill()
|
||||
return
|
||||
}
|
||||
|
||||
// signal_stop - stops the process, you can resume it with p.signal_continue()
|
||||
pub fn (mut p Process) signal_stop() {
|
||||
if p.status != .running {
|
||||
return
|
||||
}
|
||||
p._signal_stop()
|
||||
p.status = .stopped
|
||||
return
|
||||
}
|
||||
|
||||
// signal_continue - tell a stopped process to continue/resume its work
|
||||
pub fn (mut p Process) signal_continue() {
|
||||
if p.status != .stopped {
|
||||
return
|
||||
}
|
||||
p._signal_continue()
|
||||
p.status = .running
|
||||
return
|
||||
}
|
||||
|
||||
// wait - wait for a process to finish.
|
||||
// NB: You have to call p.wait(), otherwise a finished process
|
||||
// would get to a zombie state, and its resources will not get
|
||||
// released fully, until its parent process exits.
|
||||
// NB: This call will block the calling process until the child
|
||||
// process is finished.
|
||||
pub fn (mut p Process) wait() {
|
||||
if p.status == .not_started {
|
||||
p._spawn()
|
||||
}
|
||||
if p.status !in [.running, .stopped] {
|
||||
return
|
||||
}
|
||||
p._wait()
|
||||
return
|
||||
}
|
||||
|
||||
// close - free the OS resources associated with the process.
|
||||
// Can be called multiple times, but will free the resources just once.
|
||||
// This sets the process state to .closed, which is final.
|
||||
pub fn (mut p Process) close() {
|
||||
if p.status in [.not_started, .closed] {
|
||||
return
|
||||
}
|
||||
p.status = .closed
|
||||
$if !windows {
|
||||
for i in 0 .. 3 {
|
||||
if p.stdio_fd[i] != 0 {
|
||||
fd_close(p.stdio_fd[i])
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[unsafe]
|
||||
pub fn (mut p Process) free() {
|
||||
p.close()
|
||||
unsafe {
|
||||
p.filename.free()
|
||||
p.err.free()
|
||||
p.args.free()
|
||||
p.env.free()
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// _spawn - should not be called directly, but only by p.run()/p.wait() .
|
||||
// It encapsulates the fork/execve mechanism that allows the
|
||||
// asynchronous starting of the new child process.
|
||||
fn (mut p Process) _spawn() int {
|
||||
if !p.env_is_custom {
|
||||
p.env = []string{}
|
||||
current_environment := environ()
|
||||
for k, v in current_environment {
|
||||
p.env << '$k=$v'
|
||||
}
|
||||
}
|
||||
mut pid := 0
|
||||
$if windows {
|
||||
pid = p.win_spawn_process()
|
||||
} $else {
|
||||
pid = p.unix_spawn_process()
|
||||
}
|
||||
p.pid = pid
|
||||
p.status = .running
|
||||
return 0
|
||||
}
|
||||
|
||||
// is_alive - query whether the process p.pid is still alive
|
||||
pub fn (mut p Process) is_alive() bool {
|
||||
if p.status in [.running, .stopped] {
|
||||
return p._is_alive()
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
//
|
||||
pub fn (mut p Process) set_redirect_stdio() {
|
||||
p.use_stdio_ctl = true
|
||||
return
|
||||
}
|
||||
|
||||
pub fn (mut p Process) stdin_write(s string) {
|
||||
p._check_redirection_call('stdin_write')
|
||||
$if windows {
|
||||
p.win_write_string(0, s)
|
||||
} $else {
|
||||
fd_write(p.stdio_fd[0], s)
|
||||
}
|
||||
}
|
||||
|
||||
// will read from stdout pipe, will only return when EOF (end of file) or data
|
||||
// means this will block unless there is data
|
||||
pub fn (mut p Process) stdout_slurp() string {
|
||||
p._check_redirection_call('stdout_slurp')
|
||||
$if windows {
|
||||
return p.win_slurp(1)
|
||||
} $else {
|
||||
return fd_slurp(p.stdio_fd[1]).join('')
|
||||
}
|
||||
}
|
||||
|
||||
// read from stderr pipe, wait for data or EOF
|
||||
pub fn (mut p Process) stderr_slurp() string {
|
||||
p._check_redirection_call('stderr_slurp')
|
||||
$if windows {
|
||||
return p.win_slurp(2)
|
||||
} $else {
|
||||
return fd_slurp(p.stdio_fd[2]).join('')
|
||||
}
|
||||
}
|
||||
|
||||
// read from stdout, return if data or not
|
||||
pub fn (mut p Process) stdout_read() string {
|
||||
p._check_redirection_call('stdout_read')
|
||||
$if windows {
|
||||
s, _ := p.win_read_string(1, 4096)
|
||||
return s
|
||||
} $else {
|
||||
s, _ := fd_read(p.stdio_fd[1], 4096)
|
||||
return s
|
||||
}
|
||||
}
|
||||
|
||||
pub fn (mut p Process) stderr_read() string {
|
||||
p._check_redirection_call('stderr_read')
|
||||
$if windows {
|
||||
s, _ := p.win_read_string(2, 4096)
|
||||
return s
|
||||
} $else {
|
||||
s, _ := fd_read(p.stdio_fd[2], 4096)
|
||||
return s
|
||||
}
|
||||
}
|
||||
|
||||
// _check_redirection_call - should be called just by stdxxx methods
|
||||
fn (mut p Process) _check_redirection_call(fn_name string) {
|
||||
if !p.use_stdio_ctl {
|
||||
panic('Call p.set_redirect_stdio() before calling p.$fn_name')
|
||||
}
|
||||
if p.status == .not_started {
|
||||
panic('Call p.${fn_name}() after you have called p.run()')
|
||||
}
|
||||
}
|
||||
|
||||
// _signal_stop - should not be called directly, except by p.signal_stop
|
||||
fn (mut p Process) _signal_stop() {
|
||||
$if windows {
|
||||
p.win_stop_process()
|
||||
} $else {
|
||||
p.unix_stop_process()
|
||||
}
|
||||
}
|
||||
|
||||
// _signal_continue - should not be called directly, just by p.signal_continue
|
||||
fn (mut p Process) _signal_continue() {
|
||||
$if windows {
|
||||
p.win_resume_process()
|
||||
} $else {
|
||||
p.unix_resume_process()
|
||||
}
|
||||
}
|
||||
|
||||
// _signal_kill - should not be called directly, except by p.signal_kill
|
||||
fn (mut p Process) _signal_kill() {
|
||||
$if windows {
|
||||
p.win_kill_process()
|
||||
} $else {
|
||||
p.unix_kill_process()
|
||||
}
|
||||
}
|
||||
|
||||
// _signal_pgkill - should not be called directly, except by p.signal_pgkill
|
||||
fn (mut p Process) _signal_pgkill() {
|
||||
$if windows {
|
||||
p.win_kill_pgroup()
|
||||
} $else {
|
||||
p.unix_kill_pgroup()
|
||||
}
|
||||
}
|
||||
|
||||
// _wait - should not be called directly, except by p.wait()
|
||||
fn (mut p Process) _wait() {
|
||||
$if windows {
|
||||
p.win_wait()
|
||||
} $else {
|
||||
p.unix_wait()
|
||||
}
|
||||
}
|
||||
|
||||
// _is_alive - should not be called directly, except by p.is_alive()
|
||||
fn (mut p Process) _is_alive() bool {
|
||||
$if windows {
|
||||
return p.win_is_alive()
|
||||
} $else {
|
||||
return p.unix_is_alive()
|
||||
}
|
||||
}
|
||||
|
||||
// run - starts the new process
|
||||
pub fn (mut p Process) run() {
|
||||
if p.status != .not_started {
|
||||
return
|
||||
}
|
||||
p._spawn()
|
||||
return
|
||||
}
|
|
@ -0,0 +1,117 @@
|
|||
module os
|
||||
|
||||
#const $child_process = require('child_process')
|
||||
|
||||
// new_process - create a new process descriptor
|
||||
// NB: new does NOT start the new process.
|
||||
// That is done because you may want to customize it first,
|
||||
// by calling different set_ methods on it.
|
||||
// In order to start it, call p.run() or p.wait()
|
||||
pub fn new_process(filename string) &Process {
|
||||
return &Process{
|
||||
filename: filename
|
||||
stdio_fd: [-1, -1, -1]!
|
||||
}
|
||||
}
|
||||
|
||||
fn (mut p Process) spawn_internal() {
|
||||
#p.val.pid = $child_process.spawn(
|
||||
#p.val.filename+'',
|
||||
#p.val.args.arr.map((x) => x.valueOf() + ''),
|
||||
#{
|
||||
#env: (p.val.env_is_custom ? p.val.env : $process.env),
|
||||
#})
|
||||
#p.val.pid.on('error', function (err) { builtin.panic('Failed to start subprocess') })
|
||||
|
||||
p.status = .running
|
||||
// todo(playX): stderr,stdin
|
||||
if p.use_stdio_ctl {
|
||||
#p.val.pid.stdout.pipe(process.stdout)
|
||||
#p.val.pid.stdin.pipe(process.stdin)
|
||||
#p.val.pid.stderr.pipe(process.stderr)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn (mut p Process) run() {
|
||||
if p.status != .not_started {
|
||||
return
|
||||
}
|
||||
p.spawn_internal()
|
||||
return
|
||||
}
|
||||
|
||||
pub fn (mut p Process) signal_kill() {
|
||||
if p.status !in [.running, .stopped] {
|
||||
return
|
||||
}
|
||||
#p.val.pid.kill('SIGKILL');
|
||||
|
||||
p.status = .aborted
|
||||
}
|
||||
|
||||
pub fn (mut p Process) signal_stop() {
|
||||
if p.status !in [.running, .stopped] {
|
||||
return
|
||||
}
|
||||
#p.val.pid.kill('SIGSTOP');
|
||||
|
||||
p.status = .aborted
|
||||
}
|
||||
|
||||
pub fn (mut p Process) signal_continue() {
|
||||
if p.status != .stopped {
|
||||
return
|
||||
}
|
||||
#p.val.pid.kill('SIGCONT');
|
||||
|
||||
p.status = .running
|
||||
return
|
||||
}
|
||||
|
||||
pub fn (mut p Process) wait() {
|
||||
if p.status == .not_started {
|
||||
p.spawn_internal()
|
||||
}
|
||||
if p.status !in [.running, .stopped] {
|
||||
return
|
||||
}
|
||||
|
||||
p.wait_internal()
|
||||
return
|
||||
}
|
||||
|
||||
fn (mut p Process) wait_internal() {
|
||||
#p.val.pid.on('exit', function (code) { console.log(code) })
|
||||
}
|
||||
|
||||
pub fn (mut p Process) set_redirect_stdio() {
|
||||
p.use_stdio_ctl = true
|
||||
return
|
||||
}
|
||||
|
||||
pub fn (mut p Process) stdin_write(s string) {
|
||||
p.check_redirection_call('stdin_write')
|
||||
#p.val.pid.stdin.write(s)
|
||||
}
|
||||
|
||||
// todo(playX): probably does not work
|
||||
|
||||
// will read from stdout pipe, will only return when EOF (end of file) or data
|
||||
// means this will block unless there is data
|
||||
pub fn (mut p Process) stdout_slurp() string {
|
||||
p.check_redirection_call('stdout_slurp')
|
||||
mut res := ''
|
||||
#p.val.pid.stdout.on('data', function (data) { res = new builtin.string(data) })
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
// _check_redirection_call - should be called just by stdxxx methods
|
||||
fn (mut p Process) check_redirection_call(fn_name string) {
|
||||
if !p.use_stdio_ctl {
|
||||
panic('Call p.set_redirect_stdio() before calling p.$fn_name')
|
||||
}
|
||||
if p.status == .not_started {
|
||||
panic('Call p.${fn_name}() after you have called p.run()')
|
||||
}
|
||||
}
|
|
@ -68,250 +68,3 @@ pub fn (mut p Process) set_environment(envs map[string]string) {
|
|||
}
|
||||
return
|
||||
}
|
||||
|
||||
// run - starts the new process
|
||||
pub fn (mut p Process) run() {
|
||||
if p.status != .not_started {
|
||||
return
|
||||
}
|
||||
p._spawn()
|
||||
return
|
||||
}
|
||||
|
||||
// signal_kill - kills the process, after that it is no longer running
|
||||
pub fn (mut p Process) signal_kill() {
|
||||
if p.status !in [.running, .stopped] {
|
||||
return
|
||||
}
|
||||
p._signal_kill()
|
||||
p.status = .aborted
|
||||
return
|
||||
}
|
||||
|
||||
// signal_pgkill - kills the whole process group
|
||||
pub fn (mut p Process) signal_pgkill() {
|
||||
if p.status !in [.running, .stopped] {
|
||||
return
|
||||
}
|
||||
p._signal_pgkill()
|
||||
return
|
||||
}
|
||||
|
||||
// signal_stop - stops the process, you can resume it with p.signal_continue()
|
||||
pub fn (mut p Process) signal_stop() {
|
||||
if p.status != .running {
|
||||
return
|
||||
}
|
||||
p._signal_stop()
|
||||
p.status = .stopped
|
||||
return
|
||||
}
|
||||
|
||||
// signal_continue - tell a stopped process to continue/resume its work
|
||||
pub fn (mut p Process) signal_continue() {
|
||||
if p.status != .stopped {
|
||||
return
|
||||
}
|
||||
p._signal_continue()
|
||||
p.status = .running
|
||||
return
|
||||
}
|
||||
|
||||
// wait - wait for a process to finish.
|
||||
// NB: You have to call p.wait(), otherwise a finished process
|
||||
// would get to a zombie state, and its resources will not get
|
||||
// released fully, until its parent process exits.
|
||||
// NB: This call will block the calling process until the child
|
||||
// process is finished.
|
||||
pub fn (mut p Process) wait() {
|
||||
if p.status == .not_started {
|
||||
p._spawn()
|
||||
}
|
||||
if p.status !in [.running, .stopped] {
|
||||
return
|
||||
}
|
||||
p._wait()
|
||||
return
|
||||
}
|
||||
|
||||
// close - free the OS resources associated with the process.
|
||||
// Can be called multiple times, but will free the resources just once.
|
||||
// This sets the process state to .closed, which is final.
|
||||
pub fn (mut p Process) close() {
|
||||
if p.status in [.not_started, .closed] {
|
||||
return
|
||||
}
|
||||
p.status = .closed
|
||||
$if !windows {
|
||||
for i in 0 .. 3 {
|
||||
if p.stdio_fd[i] != 0 {
|
||||
fd_close(p.stdio_fd[i])
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[unsafe]
|
||||
pub fn (mut p Process) free() {
|
||||
p.close()
|
||||
unsafe {
|
||||
p.filename.free()
|
||||
p.err.free()
|
||||
p.args.free()
|
||||
p.env.free()
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// _spawn - should not be called directly, but only by p.run()/p.wait() .
|
||||
// It encapsulates the fork/execve mechanism that allows the
|
||||
// asynchronous starting of the new child process.
|
||||
fn (mut p Process) _spawn() int {
|
||||
if !p.env_is_custom {
|
||||
p.env = []string{}
|
||||
current_environment := environ()
|
||||
for k, v in current_environment {
|
||||
p.env << '$k=$v'
|
||||
}
|
||||
}
|
||||
mut pid := 0
|
||||
$if windows {
|
||||
pid = p.win_spawn_process()
|
||||
} $else {
|
||||
pid = p.unix_spawn_process()
|
||||
}
|
||||
p.pid = pid
|
||||
p.status = .running
|
||||
return 0
|
||||
}
|
||||
|
||||
// is_alive - query whether the process p.pid is still alive
|
||||
pub fn (mut p Process) is_alive() bool {
|
||||
if p.status in [.running, .stopped] {
|
||||
return p._is_alive()
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
//
|
||||
pub fn (mut p Process) set_redirect_stdio() {
|
||||
p.use_stdio_ctl = true
|
||||
return
|
||||
}
|
||||
|
||||
pub fn (mut p Process) stdin_write(s string) {
|
||||
p._check_redirection_call('stdin_write')
|
||||
$if windows {
|
||||
p.win_write_string(0, s)
|
||||
} $else {
|
||||
fd_write(p.stdio_fd[0], s)
|
||||
}
|
||||
}
|
||||
|
||||
// will read from stdout pipe, will only return when EOF (end of file) or data
|
||||
// means this will block unless there is data
|
||||
pub fn (mut p Process) stdout_slurp() string {
|
||||
p._check_redirection_call('stdout_slurp')
|
||||
$if windows {
|
||||
return p.win_slurp(1)
|
||||
} $else {
|
||||
return fd_slurp(p.stdio_fd[1]).join('')
|
||||
}
|
||||
}
|
||||
|
||||
// read from stderr pipe, wait for data or EOF
|
||||
pub fn (mut p Process) stderr_slurp() string {
|
||||
p._check_redirection_call('stderr_slurp')
|
||||
$if windows {
|
||||
return p.win_slurp(2)
|
||||
} $else {
|
||||
return fd_slurp(p.stdio_fd[2]).join('')
|
||||
}
|
||||
}
|
||||
|
||||
// read from stdout, return if data or not
|
||||
pub fn (mut p Process) stdout_read() string {
|
||||
p._check_redirection_call('stdout_read')
|
||||
$if windows {
|
||||
s, _ := p.win_read_string(1, 4096)
|
||||
return s
|
||||
} $else {
|
||||
s, _ := fd_read(p.stdio_fd[1], 4096)
|
||||
return s
|
||||
}
|
||||
}
|
||||
|
||||
pub fn (mut p Process) stderr_read() string {
|
||||
p._check_redirection_call('stderr_read')
|
||||
$if windows {
|
||||
s, _ := p.win_read_string(2, 4096)
|
||||
return s
|
||||
} $else {
|
||||
s, _ := fd_read(p.stdio_fd[2], 4096)
|
||||
return s
|
||||
}
|
||||
}
|
||||
|
||||
// _check_redirection_call - should be called just by stdxxx methods
|
||||
fn (mut p Process) _check_redirection_call(fn_name string) {
|
||||
if !p.use_stdio_ctl {
|
||||
panic('Call p.set_redirect_stdio() before calling p.$fn_name')
|
||||
}
|
||||
if p.status == .not_started {
|
||||
panic('Call p.${fn_name}() after you have called p.run()')
|
||||
}
|
||||
}
|
||||
|
||||
// _signal_stop - should not be called directly, except by p.signal_stop
|
||||
fn (mut p Process) _signal_stop() {
|
||||
$if windows {
|
||||
p.win_stop_process()
|
||||
} $else {
|
||||
p.unix_stop_process()
|
||||
}
|
||||
}
|
||||
|
||||
// _signal_continue - should not be called directly, just by p.signal_continue
|
||||
fn (mut p Process) _signal_continue() {
|
||||
$if windows {
|
||||
p.win_resume_process()
|
||||
} $else {
|
||||
p.unix_resume_process()
|
||||
}
|
||||
}
|
||||
|
||||
// _signal_kill - should not be called directly, except by p.signal_kill
|
||||
fn (mut p Process) _signal_kill() {
|
||||
$if windows {
|
||||
p.win_kill_process()
|
||||
} $else {
|
||||
p.unix_kill_process()
|
||||
}
|
||||
}
|
||||
|
||||
// _signal_pgkill - should not be called directly, except by p.signal_pgkill
|
||||
fn (mut p Process) _signal_pgkill() {
|
||||
$if windows {
|
||||
p.win_kill_pgroup()
|
||||
} $else {
|
||||
p.unix_kill_pgroup()
|
||||
}
|
||||
}
|
||||
|
||||
// _wait - should not be called directly, except by p.wait()
|
||||
fn (mut p Process) _wait() {
|
||||
$if windows {
|
||||
p.win_wait()
|
||||
} $else {
|
||||
p.unix_wait()
|
||||
}
|
||||
}
|
||||
|
||||
// _is_alive - should not be called directly, except by p.is_alive()
|
||||
fn (mut p Process) _is_alive() bool {
|
||||
$if windows {
|
||||
return p.win_is_alive()
|
||||
} $else {
|
||||
return p.unix_is_alive()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -348,7 +348,7 @@ fn (mut g JsGen) gen_builtin_type_defs() {
|
|||
'f32', 'f64', 'float_literal' {
|
||||
g.gen_builtin_prototype(
|
||||
typ_name: typ_name
|
||||
constructor: 'this.val = +val'
|
||||
constructor: 'this.val = Number(val)'
|
||||
default_value: 'new Number(0)'
|
||||
to_jsval: '+this'
|
||||
)
|
||||
|
|
|
@ -1595,6 +1595,7 @@ fn (mut g JsGen) gen_method_call(it ast.CallExpr) bool {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// interfaces require dynamic dispatch. To obtain method table we use getPrototypeOf
|
||||
g.write('Object.getPrototypeOf(')
|
||||
g.expr(it.left)
|
||||
|
@ -1660,6 +1661,15 @@ fn (mut g JsGen) gen_call_expr(it ast.CallExpr) {
|
|||
}
|
||||
g.call_stack << it
|
||||
mut name := g.js_name(it.name)
|
||||
ret_sym := g.table.get_type_symbol(it.return_type)
|
||||
if it.language == .js && ret_sym.name in js.v_types && ret_sym.name != 'void' {
|
||||
g.write('new ')
|
||||
if g.ns.name != 'builtin' {
|
||||
g.write('builtin.')
|
||||
}
|
||||
g.write(ret_sym.name)
|
||||
g.write('(')
|
||||
}
|
||||
call_return_is_optional := it.return_type.has_flag(.optional)
|
||||
if call_return_is_optional {
|
||||
g.writeln('(function(){')
|
||||
|
@ -1717,6 +1727,9 @@ fn (mut g JsGen) gen_call_expr(it ast.CallExpr) {
|
|||
g.dec_indent()
|
||||
g.write('})()')
|
||||
}
|
||||
if it.language == .js && ret_sym.name in js.v_types && ret_sym.name != 'void' {
|
||||
g.write(')')
|
||||
}
|
||||
g.call_stack.delete_last()
|
||||
}
|
||||
|
||||
|
@ -1761,7 +1774,7 @@ fn (mut g JsGen) need_tmp_var_in_match(node ast.MatchExpr) bool {
|
|||
return false
|
||||
}
|
||||
|
||||
fn (mut g JsGen) match_expr_classic(node ast.MatchExpr, is_expr bool, cond_var string, tmp_var string) {
|
||||
fn (mut g JsGen) match_expr_classic(node ast.MatchExpr, is_expr bool, cond_var MatchCond, tmp_var string) {
|
||||
type_sym := g.table.get_type_symbol(node.cond_type)
|
||||
for j, branch in node.branches {
|
||||
is_last := j == node.branches.len - 1
|
||||
|
@ -1801,27 +1814,37 @@ fn (mut g JsGen) match_expr_classic(node ast.MatchExpr, is_expr bool, cond_var s
|
|||
}
|
||||
match type_sym.kind {
|
||||
.array {
|
||||
g.write('vEq($cond_var, ')
|
||||
g.write('vEq(')
|
||||
g.match_cond(cond_var)
|
||||
g.write(',')
|
||||
g.expr(expr)
|
||||
g.write(')')
|
||||
}
|
||||
.array_fixed {
|
||||
g.write('vEq($cond_var, ')
|
||||
g.write('vEq(')
|
||||
g.match_cond(cond_var)
|
||||
g.write(',')
|
||||
g.expr(expr)
|
||||
g.write(')')
|
||||
}
|
||||
.map {
|
||||
g.write('vEq($cond_var, ')
|
||||
g.write('vEq(')
|
||||
g.match_cond(cond_var)
|
||||
g.write(',')
|
||||
g.expr(expr)
|
||||
g.write(')')
|
||||
}
|
||||
.string {
|
||||
g.write('vEq($cond_var, ')
|
||||
g.write('vEq(')
|
||||
g.match_cond(cond_var)
|
||||
g.write(',')
|
||||
g.expr(expr)
|
||||
g.write(')')
|
||||
}
|
||||
.struct_ {
|
||||
g.write('vEq($cond_var, ')
|
||||
g.write('vEq(')
|
||||
g.match_cond(cond_var)
|
||||
g.write(',')
|
||||
g.expr(expr)
|
||||
g.write(')')
|
||||
}
|
||||
|
@ -1837,15 +1860,19 @@ fn (mut g JsGen) match_expr_classic(node ast.MatchExpr, is_expr bool, cond_var s
|
|||
}
|
||||
g.write('(')
|
||||
if !skip_low {
|
||||
g.write('$cond_var >= ')
|
||||
g.match_cond(cond_var)
|
||||
g.write(' >= ')
|
||||
g.expr(expr.low)
|
||||
g.write(' && ')
|
||||
}
|
||||
g.write('$cond_var <= ')
|
||||
g.match_cond(cond_var)
|
||||
g.write(' <= ')
|
||||
g.expr(expr.high)
|
||||
g.write(')')
|
||||
} else {
|
||||
g.write('vEq($cond_var,')
|
||||
g.write('vEq(')
|
||||
g.match_cond(cond_var)
|
||||
g.write(',')
|
||||
g.expr(expr)
|
||||
g.write(')')
|
||||
}
|
||||
|
@ -1865,6 +1892,27 @@ fn (mut g JsGen) match_expr_classic(node ast.MatchExpr, is_expr bool, cond_var s
|
|||
}
|
||||
}
|
||||
|
||||
type MatchCond = CondExpr | CondString
|
||||
|
||||
struct CondString {
|
||||
s string
|
||||
}
|
||||
|
||||
struct CondExpr {
|
||||
expr ast.Expr
|
||||
}
|
||||
|
||||
fn (mut g JsGen) match_cond(cond MatchCond) {
|
||||
match cond {
|
||||
CondString {
|
||||
g.writeln(cond.s)
|
||||
}
|
||||
CondExpr {
|
||||
g.expr(cond.expr)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn (mut g JsGen) match_expr(node ast.MatchExpr) {
|
||||
if node.cond_type == 0 {
|
||||
g.writeln('// match 0')
|
||||
|
@ -1873,16 +1921,22 @@ fn (mut g JsGen) match_expr(node ast.MatchExpr) {
|
|||
prev := g.inside_ternary
|
||||
need_tmp_var := g.need_tmp_var_in_match(node)
|
||||
is_expr := (node.is_expr && node.return_type != ast.void_type) || g.inside_ternary
|
||||
mut cond_var := ''
|
||||
mut cond_var := MatchCond(CondString{''})
|
||||
mut tmp_var := ''
|
||||
if is_expr && !need_tmp_var {
|
||||
g.inside_ternary = true
|
||||
}
|
||||
|
||||
cond_var = g.new_tmp_var()
|
||||
g.write('let $cond_var = ')
|
||||
if node.cond is ast.Ident || node.cond is ast.SelectorExpr || node.cond is ast.IntegerLiteral
|
||||
|| node.cond is ast.StringLiteral || node.cond is ast.FloatLiteral {
|
||||
cond_var = CondExpr{node.cond}
|
||||
} else {
|
||||
s := g.new_tmp_var()
|
||||
cond_var = CondString{s}
|
||||
g.write('let $s = ')
|
||||
g.expr(node.cond)
|
||||
g.write(';')
|
||||
g.writeln(';')
|
||||
}
|
||||
if need_tmp_var {
|
||||
tmp_var = g.new_tmp_var()
|
||||
g.writeln('let $tmp_var = undefined;')
|
||||
|
@ -1927,7 +1981,7 @@ fn (mut g JsGen) stmts_with_tmp_var(stmts []ast.Stmt, tmp_var string) {
|
|||
}
|
||||
}
|
||||
|
||||
fn (mut g JsGen) match_expr_sumtype(node ast.MatchExpr, is_expr bool, cond_var string, tmp_var string) {
|
||||
fn (mut g JsGen) match_expr_sumtype(node ast.MatchExpr, is_expr bool, cond_var MatchCond, tmp_var string) {
|
||||
for j, branch in node.branches {
|
||||
mut sumtype_index := 0
|
||||
for {
|
||||
|
@ -1954,7 +2008,7 @@ fn (mut g JsGen) match_expr_sumtype(node ast.MatchExpr, is_expr bool, cond_var s
|
|||
} else {
|
||||
g.write('if (')
|
||||
}
|
||||
g.write(cond_var)
|
||||
g.match_cond(cond_var)
|
||||
if sym.kind == .sum_type {
|
||||
g.write(' instanceof ')
|
||||
g.expr(branch.exprs[sumtype_index])
|
||||
|
@ -2669,7 +2723,7 @@ fn (mut g JsGen) gen_float_literal_expr(it ast.FloatLiteral) {
|
|||
// TODO: call.language always seems to be "v", parser bug?
|
||||
if g.call_stack.len > 0 {
|
||||
call := g.call_stack[g.call_stack.len - 1]
|
||||
// if call.language == .js {
|
||||
if call.language == .js {
|
||||
for i, t in call.args {
|
||||
if t.expr is ast.FloatLiteral {
|
||||
if t.expr == it {
|
||||
|
@ -2682,7 +2736,7 @@ fn (mut g JsGen) gen_float_literal_expr(it ast.FloatLiteral) {
|
|||
}
|
||||
}
|
||||
}
|
||||
//}
|
||||
}
|
||||
}
|
||||
|
||||
// Skip cast if type is the same as the parrent caster
|
||||
|
|
Loading…
Reference in New Issue