v test-fmt: reformat some skipped files, comment on the remaining ones
parent
e36f11750b
commit
3795aaab5c
|
@ -2,10 +2,8 @@ module main
|
||||||
|
|
||||||
// This tool regenerates V's bootstrap .c files
|
// This tool regenerates V's bootstrap .c files
|
||||||
// every time the V master branch is updated.
|
// every time the V master branch is updated.
|
||||||
|
|
||||||
// if run with the --serve flag it will run in webhook
|
// if run with the --serve flag it will run in webhook
|
||||||
// server mode awaiting a request to http://host:port/genhook
|
// server mode awaiting a request to http://host:port/genhook
|
||||||
|
|
||||||
// available command line flags:
|
// available command line flags:
|
||||||
// --work-dir gen_vc's working directory
|
// --work-dir gen_vc's working directory
|
||||||
// --purge force purge the local repositories
|
// --purge force purge the local repositories
|
||||||
|
@ -15,7 +13,6 @@ module main
|
||||||
// --log-file path to log file used when --log-to is 'file'
|
// --log-file path to log file used when --log-to is 'file'
|
||||||
// --dry-run dont push anything to remote repo
|
// --dry-run dont push anything to remote repo
|
||||||
// --force force update even if already up to date
|
// --force force update even if already up to date
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import log
|
import log
|
||||||
import flag
|
import flag
|
||||||
|
@ -24,54 +21,54 @@ import vweb
|
||||||
import net.urllib
|
import net.urllib
|
||||||
|
|
||||||
// git credentials
|
// git credentials
|
||||||
const(
|
const (
|
||||||
git_username = os.getenv('GITUSER')
|
git_username = os.getenv('GITUSER')
|
||||||
git_password = os.getenv('GITPASS')
|
git_password = os.getenv('GITPASS')
|
||||||
)
|
)
|
||||||
|
|
||||||
// repository
|
// repository
|
||||||
const(
|
const (
|
||||||
// git repo
|
// git repo
|
||||||
git_repo_v = 'github.com/vlang/v'
|
git_repo_v = 'github.com/vlang/v'
|
||||||
git_repo_vc = 'github.com/vlang/vc'
|
git_repo_vc = 'github.com/vlang/vc'
|
||||||
// local repo directories
|
// local repo directories
|
||||||
git_repo_dir_v = 'v'
|
git_repo_dir_v = 'v'
|
||||||
git_repo_dir_vc = 'vc'
|
git_repo_dir_vc = 'vc'
|
||||||
)
|
)
|
||||||
|
|
||||||
// gen_vc
|
// gen_vc
|
||||||
const(
|
const (
|
||||||
// name
|
// name
|
||||||
app_name = 'gen_vc'
|
app_name = 'gen_vc'
|
||||||
// version
|
// version
|
||||||
app_version = '0.1.2'
|
app_version = '0.1.2'
|
||||||
// description
|
// description
|
||||||
app_description = 'This tool regenerates V\'s bootstrap .c files every time the V master branch is updated.'
|
app_description = "This tool regenerates V\'s bootstrap .c files every time the V master branch is updated."
|
||||||
// assume something went wrong if file size less than this
|
// assume something went wrong if file size less than this
|
||||||
too_short_file_limit = 5000
|
too_short_file_limit = 5000
|
||||||
// create a .c file for these os's
|
// create a .c file for these os's
|
||||||
vc_build_oses = [
|
vc_build_oses = [
|
||||||
'nix', // all nix based os
|
'nix', // all nix based os
|
||||||
'windows'
|
'windows',
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
// default options (overridden by flags)
|
// default options (overridden by flags)
|
||||||
const(
|
const (
|
||||||
// gen_vc working directory
|
// gen_vc working directory
|
||||||
work_dir = '/tmp/gen_vc'
|
work_dir = '/tmp/gen_vc'
|
||||||
// dont push anything to remote repo
|
// dont push anything to remote repo
|
||||||
dry_run = false
|
dry_run = false
|
||||||
// server port
|
// server port
|
||||||
server_port = 7171
|
server_port = 7171
|
||||||
// log file
|
// log file
|
||||||
log_file = '$work_dir/log.txt'
|
log_file = '$work_dir/log.txt'
|
||||||
// log_to is either 'file' or 'terminal'
|
// log_to is either 'file' or 'terminal'
|
||||||
log_to = 'terminal'
|
log_to = 'terminal'
|
||||||
)
|
)
|
||||||
|
|
||||||
// errors
|
// errors
|
||||||
const(
|
const (
|
||||||
err_msg_build = 'error building'
|
err_msg_build = 'error building'
|
||||||
err_msg_make = 'make failed'
|
err_msg_make = 'make failed'
|
||||||
err_msg_gen_c = 'failed to generate .c file'
|
err_msg_gen_c = 'failed to generate .c file'
|
||||||
|
@ -81,9 +78,9 @@ const(
|
||||||
struct GenVC {
|
struct GenVC {
|
||||||
// logger
|
// logger
|
||||||
// flag options
|
// flag options
|
||||||
options FlagOptions
|
options FlagOptions
|
||||||
mut:
|
mut:
|
||||||
logger &log.Log
|
logger &log.Log
|
||||||
// true if error was experienced running generate
|
// true if error was experienced running generate
|
||||||
gen_error bool
|
gen_error bool
|
||||||
}
|
}
|
||||||
|
@ -109,23 +106,21 @@ struct FlagOptions {
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
mut fp := flag.new_flag_parser(os.args.clone())
|
mut fp := flag.new_flag_parser(os.args.clone())
|
||||||
|
|
||||||
fp.application(app_name)
|
fp.application(app_name)
|
||||||
fp.version(app_version)
|
fp.version(app_version)
|
||||||
fp.description(app_description)
|
fp.description(app_description)
|
||||||
fp.skip_executable()
|
fp.skip_executable()
|
||||||
|
show_help := fp.bool('help', 0, false, 'Show this help screen\n')
|
||||||
show_help:=fp.bool('help', 0, false, 'Show this help screen\n')
|
|
||||||
flag_options := parse_flags(mut fp)
|
flag_options := parse_flags(mut fp)
|
||||||
|
if show_help {
|
||||||
if show_help { println( fp.usage() ) exit(0) }
|
println(fp.usage())
|
||||||
|
exit(0)
|
||||||
|
}
|
||||||
fp.finalize() or {
|
fp.finalize() or {
|
||||||
eprintln(err)
|
eprintln(err)
|
||||||
println(fp.usage())
|
println(fp.usage())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// webhook server mode
|
// webhook server mode
|
||||||
if flag_options.serve {
|
if flag_options.serve {
|
||||||
vweb.run<WebhookServer>(flag_options.port)
|
vweb.run<WebhookServer>(flag_options.port)
|
||||||
|
@ -142,7 +137,7 @@ fn new_gen_vc(flag_options FlagOptions) &GenVC {
|
||||||
mut logger := &log.Log{}
|
mut logger := &log.Log{}
|
||||||
logger.set_level(.debug)
|
logger.set_level(.debug)
|
||||||
if flag_options.log_to == 'file' {
|
if flag_options.log_to == 'file' {
|
||||||
logger.set_full_logpath( flag_options.log_file )
|
logger.set_full_logpath(flag_options.log_file)
|
||||||
}
|
}
|
||||||
return &GenVC{
|
return &GenVC{
|
||||||
options: flag_options
|
options: flag_options
|
||||||
|
@ -156,11 +151,11 @@ pub fn (mut ws WebhookServer) init_once() {
|
||||||
flag_options := parse_flags(mut fp)
|
flag_options := parse_flags(mut fp)
|
||||||
ws.gen_vc = new_gen_vc(flag_options)
|
ws.gen_vc = new_gen_vc(flag_options)
|
||||||
ws.gen_vc.init()
|
ws.gen_vc.init()
|
||||||
//ws.gen_vc = new_gen_vc(flag_options)
|
// ws.gen_vc = new_gen_vc(flag_options)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (mut ws WebhookServer) init() {
|
pub fn (mut ws WebhookServer) init() {
|
||||||
//ws.init_once()
|
// ws.init_once()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (mut ws WebhookServer) index() {
|
pub fn (mut ws WebhookServer) index() {
|
||||||
|
@ -185,18 +180,17 @@ pub fn (mut ws WebhookServer) genhook() {
|
||||||
pub fn (ws &WebhookServer) reset() {
|
pub fn (ws &WebhookServer) reset() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// parse flags to FlagOptions struct
|
// parse flags to FlagOptions struct
|
||||||
fn parse_flags(mut fp flag.FlagParser) FlagOptions {
|
fn parse_flags(mut fp flag.FlagParser) FlagOptions {
|
||||||
return FlagOptions{
|
return FlagOptions{
|
||||||
serve : fp.bool('serve', 0, false, 'run in webhook server mode')
|
serve: fp.bool('serve', 0, false, 'run in webhook server mode')
|
||||||
work_dir : fp.string('work-dir', 0, work_dir, 'gen_vc working directory')
|
work_dir: fp.string('work-dir', 0, work_dir, 'gen_vc working directory')
|
||||||
purge : fp.bool('purge', 0, false, 'force purge the local repositories')
|
purge: fp.bool('purge', 0, false, 'force purge the local repositories')
|
||||||
port : fp.int('port', 0, server_port, 'port for web server to listen on')
|
port: fp.int('port', 0, server_port, 'port for web server to listen on')
|
||||||
log_to : fp.string('log-to', 0, log_to, 'log to is \'file\' or \'terminal\'')
|
log_to: fp.string('log-to', 0, log_to, "log to is \'file\' or \'terminal\'")
|
||||||
log_file : fp.string('log-file', 0, log_file, 'log file to use when log-to is \'file\'')
|
log_file: fp.string('log-file', 0, log_file, "log file to use when log-to is \'file\'")
|
||||||
dry_run : fp.bool('dry-run', 0, dry_run, 'when specified dont push anything to remote repo')
|
dry_run: fp.bool('dry-run', 0, dry_run, 'when specified dont push anything to remote repo')
|
||||||
force : fp.bool('force', 0, false, 'force update even if already up to date')
|
force: fp.bool('force', 0, false, 'force update even if already up to date')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -212,11 +206,12 @@ fn (mut gen_vc GenVC) init() {
|
||||||
fn (mut gen_vc GenVC) generate() {
|
fn (mut gen_vc GenVC) generate() {
|
||||||
// set errors to false
|
// set errors to false
|
||||||
gen_vc.gen_error = false
|
gen_vc.gen_error = false
|
||||||
|
|
||||||
// check if gen_vc dir exists
|
// check if gen_vc dir exists
|
||||||
if !os.is_dir(gen_vc.options.work_dir) {
|
if !os.is_dir(gen_vc.options.work_dir) {
|
||||||
// try create
|
// try create
|
||||||
os.mkdir(gen_vc.options.work_dir) or { panic(err) }
|
os.mkdir(gen_vc.options.work_dir) or {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
// still dosen't exist... we have a problem
|
// still dosen't exist... we have a problem
|
||||||
if !os.is_dir(gen_vc.options.work_dir) {
|
if !os.is_dir(gen_vc.options.work_dir) {
|
||||||
gen_vc.logger.error('error creating directory: $gen_vc.options.work_dir')
|
gen_vc.logger.error('error creating directory: $gen_vc.options.work_dir')
|
||||||
|
@ -224,10 +219,8 @@ fn (mut gen_vc GenVC) generate() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// cd to gen_vc dir
|
// cd to gen_vc dir
|
||||||
os.chdir(gen_vc.options.work_dir)
|
os.chdir(gen_vc.options.work_dir)
|
||||||
|
|
||||||
// if we are not running with the --serve flag (webhook server)
|
// if we are not running with the --serve flag (webhook server)
|
||||||
// rather than deleting and re-downloading the repo each time
|
// rather than deleting and re-downloading the repo each time
|
||||||
// first check to see if the local v repo is behind master
|
// first check to see if the local v repo is behind master
|
||||||
|
@ -242,60 +235,49 @@ fn (mut gen_vc GenVC) generate() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// delete repos
|
// delete repos
|
||||||
gen_vc.purge_repos()
|
gen_vc.purge_repos()
|
||||||
|
|
||||||
// clone repos
|
// clone repos
|
||||||
gen_vc.cmd_exec('git clone --depth 1 https://$git_repo_v $git_repo_dir_v')
|
gen_vc.cmd_exec('git clone --depth 1 https://$git_repo_v $git_repo_dir_v')
|
||||||
gen_vc.cmd_exec('git clone --depth 1 https://$git_repo_vc $git_repo_dir_vc')
|
gen_vc.cmd_exec('git clone --depth 1 https://$git_repo_vc $git_repo_dir_vc')
|
||||||
|
|
||||||
// get output of git log -1 (last commit)
|
// get output of git log -1 (last commit)
|
||||||
git_log_v := gen_vc.cmd_exec('git -C $git_repo_dir_v log -1 --format="commit %H%nDate: %ci%nDate Unix: %ct%nSubject: %s"')
|
git_log_v := gen_vc.cmd_exec('git -C $git_repo_dir_v log -1 --format="commit %H%nDate: %ci%nDate Unix: %ct%nSubject: %s"')
|
||||||
git_log_vc := gen_vc.cmd_exec('git -C $git_repo_dir_vc log -1 --format="Commit %H%nDate: %ci%nDate Unix: %ct%nSubject: %s"')
|
git_log_vc := gen_vc.cmd_exec('git -C $git_repo_dir_vc log -1 --format="Commit %H%nDate: %ci%nDate Unix: %ct%nSubject: %s"')
|
||||||
|
|
||||||
// date of last commit in each repo
|
// date of last commit in each repo
|
||||||
ts_v := git_log_v.find_between('Date:', '\n').trim_space()
|
ts_v := git_log_v.find_between('Date:', '\n').trim_space()
|
||||||
ts_vc := git_log_vc.find_between('Date:', '\n').trim_space()
|
ts_vc := git_log_vc.find_between('Date:', '\n').trim_space()
|
||||||
|
|
||||||
// parse time as string to time.Time
|
// parse time as string to time.Time
|
||||||
last_commit_time_v := time.parse(ts_v) or {
|
last_commit_time_v := time.parse(ts_v) or {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
last_commit_time_vc := time.parse(ts_vc) or {
|
last_commit_time_vc := time.parse(ts_vc) or {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// git dates are in users local timezone and v time.parse does not parse
|
// git dates are in users local timezone and v time.parse does not parse
|
||||||
// timezones at the moment, so for now get unix timestamp from output also
|
// timezones at the moment, so for now get unix timestamp from output also
|
||||||
t_unix_v := git_log_v.find_between('Date Unix:', '\n').trim_space().int()
|
t_unix_v := git_log_v.find_between('Date Unix:', '\n').trim_space().int()
|
||||||
t_unix_vc := git_log_vc.find_between('Date Unix:', '\n').trim_space().int()
|
t_unix_vc := git_log_vc.find_between('Date Unix:', '\n').trim_space().int()
|
||||||
|
|
||||||
// last commit hash in v repo
|
// last commit hash in v repo
|
||||||
last_commit_hash_v := git_log_v.find_between('commit', '\n').trim_space()
|
last_commit_hash_v := git_log_v.find_between('commit', '\n').trim_space()
|
||||||
last_commit_hash_v_short := last_commit_hash_v[..7]
|
last_commit_hash_v_short := last_commit_hash_v[..7]
|
||||||
|
|
||||||
// subject
|
// subject
|
||||||
last_commit_subject := git_log_v.find_between('Subject:', '\n').trim_space().replace('"', '\\"')
|
last_commit_subject := git_log_v.find_between('Subject:', '\n').trim_space().replace('"',
|
||||||
|
'\\"')
|
||||||
// log some info
|
// log some info
|
||||||
gen_vc.logger.debug('last commit time ($git_repo_v): ' + last_commit_time_v.format_ss())
|
gen_vc.logger.debug('last commit time ($git_repo_v): ' + last_commit_time_v.format_ss())
|
||||||
gen_vc.logger.debug('last commit time ($git_repo_vc): ' + last_commit_time_vc.format_ss())
|
gen_vc.logger.debug('last commit time ($git_repo_vc): ' + last_commit_time_vc.format_ss())
|
||||||
gen_vc.logger.debug('last commit hash ($git_repo_v): $last_commit_hash_v')
|
gen_vc.logger.debug('last commit hash ($git_repo_v): $last_commit_hash_v')
|
||||||
gen_vc.logger.debug('last commit subject ($git_repo_v): $last_commit_subject')
|
gen_vc.logger.debug('last commit subject ($git_repo_v): $last_commit_subject')
|
||||||
|
|
||||||
// if vc repo already has a newer commit than the v repo, assume it's up to date
|
// if vc repo already has a newer commit than the v repo, assume it's up to date
|
||||||
if t_unix_vc >= t_unix_v && !gen_vc.options.force {
|
if t_unix_vc >= t_unix_v && !gen_vc.options.force {
|
||||||
gen_vc.logger.warn('vc repository is already up to date.')
|
gen_vc.logger.warn('vc repository is already up to date.')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// try build v for current os (linux in this case)
|
// try build v for current os (linux in this case)
|
||||||
gen_vc.cmd_exec('make -C $git_repo_dir_v')
|
gen_vc.cmd_exec('make -C $git_repo_dir_v')
|
||||||
v_exec := '$git_repo_dir_v/v'
|
v_exec := '$git_repo_dir_v/v'
|
||||||
// check if make was successful
|
// check if make was successful
|
||||||
gen_vc.assert_file_exists_and_is_not_too_short(v_exec, err_msg_make)
|
gen_vc.assert_file_exists_and_is_not_too_short(v_exec, err_msg_make)
|
||||||
|
|
||||||
// build v.c for each os
|
// build v.c for each os
|
||||||
for os_name in vc_build_oses {
|
for os_name in vc_build_oses {
|
||||||
vc_suffix := if os_name == 'nix' { '' } else { '_${os_name[..3]}' }
|
vc_suffix := if os_name == 'nix' { '' } else { '_${os_name[..3]}' }
|
||||||
|
@ -312,7 +294,6 @@ fn (mut gen_vc GenVC) generate() {
|
||||||
// add new .c file to local vc repo
|
// add new .c file to local vc repo
|
||||||
gen_vc.cmd_exec('git -C $git_repo_dir_vc add $c_file')
|
gen_vc.cmd_exec('git -C $git_repo_dir_vc add $c_file')
|
||||||
}
|
}
|
||||||
|
|
||||||
// check if the vc repo actually changed
|
// check if the vc repo actually changed
|
||||||
git_status := gen_vc.cmd_exec('git -C $git_repo_dir_vc status')
|
git_status := gen_vc.cmd_exec('git -C $git_repo_dir_vc status')
|
||||||
if git_status.contains('nothing to commit') {
|
if git_status.contains('nothing to commit') {
|
||||||
|
@ -344,7 +325,7 @@ fn (mut gen_vc GenVC) command_execute(cmd string, dry bool) string {
|
||||||
gen_vc.logger.info('cmd: $cmd')
|
gen_vc.logger.info('cmd: $cmd')
|
||||||
r := os.exec(cmd) or {
|
r := os.exec(cmd) or {
|
||||||
gen_vc.logger.error('$err_msg_cmd_x: "$cmd" could not start.')
|
gen_vc.logger.error('$err_msg_cmd_x: "$cmd" could not start.')
|
||||||
gen_vc.logger.error( err )
|
gen_vc.logger.error(err)
|
||||||
// something went wrong, better start fresh next time
|
// something went wrong, better start fresh next time
|
||||||
gen_vc.purge_repos()
|
gen_vc.purge_repos()
|
||||||
gen_vc.gen_error = true
|
gen_vc.gen_error = true
|
||||||
|
@ -383,7 +364,7 @@ fn (mut gen_vc GenVC) purge_repos() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// check if file size is too short
|
// check if file size is too short
|
||||||
fn (mut gen_vc GenVC) assert_file_exists_and_is_not_too_short(f string, emsg string){
|
fn (mut gen_vc GenVC) assert_file_exists_and_is_not_too_short(f, emsg string) {
|
||||||
if !os.exists(f) {
|
if !os.exists(f) {
|
||||||
gen_vc.logger.error('$err_msg_build: $emsg .')
|
gen_vc.logger.error('$err_msg_build: $emsg .')
|
||||||
gen_vc.gen_error = true
|
gen_vc.gen_error = true
|
||||||
|
|
|
@ -5,7 +5,7 @@ import flag
|
||||||
import scripting
|
import scripting
|
||||||
|
|
||||||
const (
|
const (
|
||||||
remote_v_repo_url = 'https://github.com/vlang/v'
|
remote_v_repo_url = 'https://github.com/vlang/v'
|
||||||
remote_vc_repo_url = 'https://github.com/vlang/vc'
|
remote_vc_repo_url = 'https://github.com/vlang/vc'
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -34,35 +34,35 @@ pub fn validate_commit_exists(commit string) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn line_to_timestamp_and_commit(line string) (int,string) {
|
pub fn line_to_timestamp_and_commit(line string) (int, string) {
|
||||||
parts := line.split(' ')
|
parts := line.split(' ')
|
||||||
return parts[0].int(),parts[1]
|
return parts[0].int(), parts[1]
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn normalized_workpath_for_commit(workdir string, commit string) string {
|
pub fn normalized_workpath_for_commit(workdir, commit string) string {
|
||||||
nc := 'v_at_' + commit.replace('^', '_').replace('-', '_').replace('/', '_')
|
nc := 'v_at_' + commit.replace('^', '_').replace('-', '_').replace('/', '_')
|
||||||
return os.real_path(workdir + os.path_separator + nc)
|
return os.real_path(workdir + os.path_separator + nc)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn prepare_vc_source(vcdir string, cdir string, commit string) (string,string) {
|
pub fn prepare_vc_source(vcdir, cdir, commit string) (string, string) {
|
||||||
scripting.chdir(cdir)
|
scripting.chdir(cdir)
|
||||||
// Building a historic v with the latest vc is not always possible ...
|
// Building a historic v with the latest vc is not always possible ...
|
||||||
// It is more likely, that the vc *at the time of the v commit*,
|
// It is more likely, that the vc *at the time of the v commit*,
|
||||||
// or slightly before that time will be able to build the historic v:
|
// or slightly before that time will be able to build the historic v:
|
||||||
vline := scripting.run('git rev-list -n1 --timestamp "$commit" ')
|
vline := scripting.run('git rev-list -n1 --timestamp "$commit" ')
|
||||||
v_timestamp,v_commithash := vgit.line_to_timestamp_and_commit(vline)
|
v_timestamp, v_commithash := line_to_timestamp_and_commit(vline)
|
||||||
vgit.check_v_commit_timestamp_before_self_rebuilding(v_timestamp)
|
check_v_commit_timestamp_before_self_rebuilding(v_timestamp)
|
||||||
scripting.chdir(vcdir)
|
scripting.chdir(vcdir)
|
||||||
scripting.run('git checkout master')
|
scripting.run('git checkout master')
|
||||||
vcbefore := scripting.run('git rev-list HEAD -n1 --timestamp --before=$v_timestamp ')
|
vcbefore := scripting.run('git rev-list HEAD -n1 --timestamp --before=$v_timestamp ')
|
||||||
_,vccommit_before := vgit.line_to_timestamp_and_commit(vcbefore)
|
_, vccommit_before := line_to_timestamp_and_commit(vcbefore)
|
||||||
scripting.run('git checkout "$vccommit_before" ')
|
scripting.run('git checkout "$vccommit_before" ')
|
||||||
scripting.run('wc *.c')
|
scripting.run('wc *.c')
|
||||||
scripting.chdir(cdir)
|
scripting.chdir(cdir)
|
||||||
return v_commithash,vccommit_before
|
return v_commithash, vccommit_before
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn clone_or_pull( remote_git_url string, local_worktree_path string ) {
|
pub fn clone_or_pull(remote_git_url, local_worktree_path string) {
|
||||||
// NB: after clone_or_pull, the current repo branch is === HEAD === master
|
// NB: after clone_or_pull, the current repo branch is === HEAD === master
|
||||||
if os.is_dir(local_worktree_path) && os.is_dir(os.join_path(local_worktree_path, '.git')) {
|
if os.is_dir(local_worktree_path) && os.is_dir(os.join_path(local_worktree_path, '.git')) {
|
||||||
// Already existing ... Just pulling in this case is faster usually.
|
// Already existing ... Just pulling in this case is faster usually.
|
||||||
|
@ -76,20 +76,20 @@ pub fn clone_or_pull( remote_git_url string, local_worktree_path string ) {
|
||||||
|
|
||||||
pub struct VGitContext {
|
pub struct VGitContext {
|
||||||
pub:
|
pub:
|
||||||
cc string = 'cc' // what compiler to use
|
cc string = 'cc' // what compiler to use
|
||||||
workdir string = '/tmp' // the base working folder
|
workdir string = '/tmp' // the base working folder
|
||||||
commit_v string = 'master' // the commit-ish that needs to be prepared
|
commit_v string = 'master' // the commit-ish that needs to be prepared
|
||||||
path_v string // where is the local working copy v repo
|
path_v string // where is the local working copy v repo
|
||||||
path_vc string // where is the local working copy vc repo
|
path_vc string // where is the local working copy vc repo
|
||||||
v_repo_url string // the remote v repo URL
|
v_repo_url string // the remote v repo URL
|
||||||
vc_repo_url string // the remote vc repo URL
|
vc_repo_url string // the remote vc repo URL
|
||||||
pub mut:
|
pub mut:
|
||||||
// these will be filled by vgitcontext.compile_oldv_if_needed()
|
// these will be filled by vgitcontext.compile_oldv_if_needed()
|
||||||
commit_v__hash string // the git commit of the v repo that should be prepared
|
commit_v__hash string // the git commit of the v repo that should be prepared
|
||||||
commit_vc_hash string // the git commit of the vc repo, corresponding to commit_v__hash
|
commit_vc_hash string // the git commit of the vc repo, corresponding to commit_v__hash
|
||||||
vexename string // v or v.exe
|
vexename string // v or v.exe
|
||||||
vexepath string // the full absolute path to the prepared v/v.exe
|
vexepath string // the full absolute path to the prepared v/v.exe
|
||||||
vvlocation string // v.v or compiler/ or cmd/v, depending on v version
|
vvlocation string // v.v or compiler/ or cmd/v, depending on v version
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (mut vgit_context VGitContext) compile_oldv_if_needed() {
|
pub fn (mut vgit_context VGitContext) compile_oldv_if_needed() {
|
||||||
|
@ -100,18 +100,17 @@ pub fn (mut vgit_context VGitContext) compile_oldv_if_needed() {
|
||||||
if 'windows' == os.user_os() {
|
if 'windows' == os.user_os() {
|
||||||
command_for_building_v_from_c_source = '$vgit_context.cc -std=c99 -municode -w -o cv.exe "$vgit_context.path_vc/v_win.c" '
|
command_for_building_v_from_c_source = '$vgit_context.cc -std=c99 -municode -w -o cv.exe "$vgit_context.path_vc/v_win.c" '
|
||||||
command_for_selfbuilding = './cv.exe -o $vgit_context.vexename {SOURCE}'
|
command_for_selfbuilding = './cv.exe -o $vgit_context.vexename {SOURCE}'
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
command_for_building_v_from_c_source = '$vgit_context.cc -std=gnu11 -w -o cv "$vgit_context.path_vc/v.c" -lm -lpthread'
|
command_for_building_v_from_c_source = '$vgit_context.cc -std=gnu11 -w -o cv "$vgit_context.path_vc/v.c" -lm -lpthread'
|
||||||
command_for_selfbuilding = './cv -o $vgit_context.vexename {SOURCE}'
|
command_for_selfbuilding = './cv -o $vgit_context.vexename {SOURCE}'
|
||||||
}
|
}
|
||||||
scripting.chdir(vgit_context.workdir)
|
scripting.chdir(vgit_context.workdir)
|
||||||
clone_or_pull( vgit_context.v_repo_url, vgit_context.path_v )
|
clone_or_pull(vgit_context.v_repo_url, vgit_context.path_v)
|
||||||
clone_or_pull( vgit_context.vc_repo_url, vgit_context.path_vc )
|
clone_or_pull(vgit_context.vc_repo_url, vgit_context.path_vc)
|
||||||
|
|
||||||
scripting.chdir(vgit_context.path_v)
|
scripting.chdir(vgit_context.path_v)
|
||||||
scripting.run('git checkout $vgit_context.commit_v')
|
scripting.run('git checkout $vgit_context.commit_v')
|
||||||
v_commithash,vccommit_before := vgit.prepare_vc_source(vgit_context.path_vc, vgit_context.path_v, vgit_context.commit_v)
|
v_commithash, vccommit_before := prepare_vc_source(vgit_context.path_vc, vgit_context.path_v,
|
||||||
|
vgit_context.commit_v)
|
||||||
vgit_context.commit_v__hash = v_commithash
|
vgit_context.commit_v__hash = v_commithash
|
||||||
vgit_context.commit_vc_hash = vccommit_before
|
vgit_context.commit_vc_hash = vccommit_before
|
||||||
if os.exists('cmd/v') {
|
if os.exists('cmd/v') {
|
||||||
|
@ -128,25 +127,24 @@ pub fn (mut vgit_context VGitContext) compile_oldv_if_needed() {
|
||||||
scripting.run(command_for_building_v_from_c_source)
|
scripting.run(command_for_building_v_from_c_source)
|
||||||
build_cmd := command_for_selfbuilding.replace('{SOURCE}', vgit_context.vvlocation)
|
build_cmd := command_for_selfbuilding.replace('{SOURCE}', vgit_context.vvlocation)
|
||||||
scripting.run(build_cmd)
|
scripting.run(build_cmd)
|
||||||
|
|
||||||
// At this point, there exists a file vgit_context.vexepath
|
// At this point, there exists a file vgit_context.vexepath
|
||||||
// which should be a valid working V executable.
|
// which should be a valid working V executable.
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct VGitOptions {
|
pub struct VGitOptions {
|
||||||
pub mut:
|
pub mut:
|
||||||
workdir string // the working folder (typically /tmp), where the tool will write
|
workdir string // the working folder (typically /tmp), where the tool will write
|
||||||
v_repo_url string // the url of the V repository. It can be a local folder path, if you want to eliminate network operations...
|
v_repo_url string // the url of the V repository. It can be a local folder path, if you want to eliminate network operations...
|
||||||
vc_repo_url string // the url of the vc repository. It can be a local folder path, if you want to eliminate network operations...
|
vc_repo_url string // the url of the vc repository. It can be a local folder path, if you want to eliminate network operations...
|
||||||
show_help bool // whether to show the usage screen
|
show_help bool // whether to show the usage screen
|
||||||
verbose bool // should the tool be much more verbose
|
verbose bool // should the tool be much more verbose
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_common_tool_options(mut context VGitOptions, mut fp flag.FlagParser) []string {
|
pub fn add_common_tool_options(mut context VGitOptions, mut fp flag.FlagParser) []string {
|
||||||
tdir := os.temp_dir()
|
tdir := os.temp_dir()
|
||||||
context.workdir = os.real_path(fp.string('workdir', `w`, tdir, 'A writable base folder. Default: $tdir'))
|
context.workdir = os.real_path(fp.string('workdir', `w`, tdir, 'A writable base folder. Default: $tdir'))
|
||||||
context.v_repo_url = fp.string('vrepo', 0, vgit.remote_v_repo_url, 'The url of the V repository. You can clone it locally too. See also --vcrepo below.')
|
context.v_repo_url = fp.string('vrepo', 0, remote_v_repo_url, 'The url of the V repository. You can clone it locally too. See also --vcrepo below.')
|
||||||
context.vc_repo_url = fp.string('vcrepo', 0, vgit.remote_vc_repo_url, 'The url of the vc repository. You can clone it
|
context.vc_repo_url = fp.string('vcrepo', 0, remote_vc_repo_url, 'The url of the vc repository. You can clone it
|
||||||
${flag.space}beforehand, and then just give the local folder
|
${flag.space}beforehand, and then just give the local folder
|
||||||
${flag.space}path here. That will eliminate the network ops
|
${flag.space}path here. That will eliminate the network ops
|
||||||
${flag.space}done by this tool, which is useful, if you want
|
${flag.space}done by this tool, which is useful, if you want
|
||||||
|
@ -154,31 +152,25 @@ ${flag.space}to script it/run it in a restrictive vps/docker.
|
||||||
')
|
')
|
||||||
context.show_help = fp.bool('help', `h`, false, 'Show this help screen.')
|
context.show_help = fp.bool('help', `h`, false, 'Show this help screen.')
|
||||||
context.verbose = fp.bool('verbose', `v`, false, 'Be more verbose.')
|
context.verbose = fp.bool('verbose', `v`, false, 'Be more verbose.')
|
||||||
|
|
||||||
if context.show_help {
|
if context.show_help {
|
||||||
println(fp.usage())
|
println(fp.usage())
|
||||||
exit(0)
|
exit(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
if context.verbose {
|
if context.verbose {
|
||||||
scripting.set_verbose(true)
|
scripting.set_verbose(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
if os.is_dir(context.v_repo_url) {
|
if os.is_dir(context.v_repo_url) {
|
||||||
context.v_repo_url = os.real_path( context.v_repo_url )
|
context.v_repo_url = os.real_path(context.v_repo_url)
|
||||||
}
|
}
|
||||||
|
|
||||||
if os.is_dir(context.vc_repo_url) {
|
if os.is_dir(context.vc_repo_url) {
|
||||||
context.vc_repo_url = os.real_path( context.vc_repo_url )
|
context.vc_repo_url = os.real_path(context.vc_repo_url)
|
||||||
}
|
}
|
||||||
|
|
||||||
commits := fp.finalize() or {
|
commits := fp.finalize() or {
|
||||||
eprintln('Error: ' + err)
|
eprintln('Error: ' + err)
|
||||||
exit(1)
|
exit(1)
|
||||||
}
|
}
|
||||||
for commit in commits {
|
for commit in commits {
|
||||||
vgit.validate_commit_exists(commit)
|
validate_commit_exists(commit)
|
||||||
}
|
}
|
||||||
|
|
||||||
return commits
|
return commits
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,7 @@ import scripting
|
||||||
import vgit
|
import vgit
|
||||||
|
|
||||||
const (
|
const (
|
||||||
tool_version = '0.0.3'
|
tool_version = '0.0.3'
|
||||||
tool_description = ' Checkout an old V and compile it as it was on specific commit.
|
tool_description = ' Checkout an old V and compile it as it was on specific commit.
|
||||||
This tool is useful, when you want to discover when something broke.
|
This tool is useful, when you want to discover when something broke.
|
||||||
It is also useful, when you just want to experiment with an older historic V.
|
It is also useful, when you just want to experiment with an older historic V.
|
||||||
|
@ -30,25 +30,25 @@ const (
|
||||||
struct Context {
|
struct Context {
|
||||||
mut:
|
mut:
|
||||||
vgo vgit.VGitOptions
|
vgo vgit.VGitOptions
|
||||||
commit_v string='master' // the commit from which you want to produce a working v compiler (this may be a commit-ish too)
|
commit_v string = 'master' // the commit from which you want to produce a working v compiler (this may be a commit-ish too)
|
||||||
commit_vc string='master' // this will be derived from commit_v
|
commit_vc string = 'master' // this will be derived from commit_v
|
||||||
commit_v_hash string // this will be filled from the commit-ish commit_v using rev-list. It IS a commit hash.
|
commit_v_hash string // this will be filled from the commit-ish commit_v using rev-list. It IS a commit hash.
|
||||||
path_v string // the full path to the v folder inside workdir.
|
path_v string // the full path to the v folder inside workdir.
|
||||||
path_vc string // the full path to the vc folder inside workdir.
|
path_vc string // the full path to the vc folder inside workdir.
|
||||||
cmd_to_run string // the command that you want to run *in* the oldv repo
|
cmd_to_run string // the command that you want to run *in* the oldv repo
|
||||||
cc string='cc' // the C compiler to use for bootstrapping.
|
cc string = 'cc' // the C compiler to use for bootstrapping.
|
||||||
cleanup bool // should the tool run a cleanup first
|
cleanup bool // should the tool run a cleanup first
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (mut c Context) compile_oldv_if_needed() {
|
fn (mut c Context) compile_oldv_if_needed() {
|
||||||
mut vgit_context := vgit.VGitContext{
|
mut vgit_context := vgit.VGitContext{
|
||||||
workdir: c.vgo.workdir
|
workdir: c.vgo.workdir
|
||||||
v_repo_url: c.vgo.v_repo_url
|
v_repo_url: c.vgo.v_repo_url
|
||||||
vc_repo_url: c.vgo.vc_repo_url
|
vc_repo_url: c.vgo.vc_repo_url
|
||||||
cc: c.cc
|
cc: c.cc
|
||||||
commit_v: c.commit_v
|
commit_v: c.commit_v
|
||||||
path_v: c.path_v
|
path_v: c.path_v
|
||||||
path_vc: c.path_vc
|
path_vc: c.path_vc
|
||||||
}
|
}
|
||||||
vgit_context.compile_oldv_if_needed()
|
vgit_context.compile_oldv_if_needed()
|
||||||
c.commit_v_hash = vgit_context.commit_v__hash
|
c.commit_v_hash = vgit_context.commit_v__hash
|
||||||
|
@ -69,10 +69,8 @@ fn main() {
|
||||||
fp.arguments_description('VCOMMIT')
|
fp.arguments_description('VCOMMIT')
|
||||||
fp.skip_executable()
|
fp.skip_executable()
|
||||||
fp.limit_free_args(1, 1)
|
fp.limit_free_args(1, 1)
|
||||||
|
|
||||||
context.cleanup = fp.bool('clean', 0, true, 'Clean before running (slower).')
|
context.cleanup = fp.bool('clean', 0, true, 'Clean before running (slower).')
|
||||||
context.cmd_to_run = fp.string('command', `c`, '', 'Command to run in the old V repo.\n')
|
context.cmd_to_run = fp.string('command', `c`, '', 'Command to run in the old V repo.\n')
|
||||||
|
|
||||||
commits := vgit.add_common_tool_options(mut context.vgo, mut fp)
|
commits := vgit.add_common_tool_options(mut context.vgo, mut fp)
|
||||||
if commits.len > 0 {
|
if commits.len > 0 {
|
||||||
context.commit_v = commits[0]
|
context.commit_v = commits[0]
|
||||||
|
@ -83,7 +81,7 @@ fn main() {
|
||||||
context.path_v = vgit.normalized_workpath_for_commit(context.vgo.workdir, context.commit_v)
|
context.path_v = vgit.normalized_workpath_for_commit(context.vgo.workdir, context.commit_v)
|
||||||
context.path_vc = vgit.normalized_workpath_for_commit(context.vgo.workdir, 'vc')
|
context.path_vc = vgit.normalized_workpath_for_commit(context.vgo.workdir, 'vc')
|
||||||
if !os.is_dir(context.vgo.workdir) {
|
if !os.is_dir(context.vgo.workdir) {
|
||||||
eprintln('Work folder: ${context.vgo.workdir} , does not exist.')
|
eprintln('Work folder: $context.vgo.workdir , does not exist.')
|
||||||
exit(2)
|
exit(2)
|
||||||
}
|
}
|
||||||
ecc := os.getenv('CC')
|
ecc := os.getenv('CC')
|
||||||
|
@ -94,9 +92,7 @@ fn main() {
|
||||||
scripting.rmrf(context.path_v)
|
scripting.rmrf(context.path_v)
|
||||||
scripting.rmrf(context.path_vc)
|
scripting.rmrf(context.path_vc)
|
||||||
}
|
}
|
||||||
|
|
||||||
context.compile_oldv_if_needed()
|
context.compile_oldv_if_needed()
|
||||||
|
|
||||||
scripting.chdir(context.path_v)
|
scripting.chdir(context.path_v)
|
||||||
scripting.cprintln('# v commit hash: $context.commit_v_hash')
|
scripting.cprintln('# v commit hash: $context.commit_v_hash')
|
||||||
scripting.cprintln('# checkout folder: $context.path_v')
|
scripting.cprintln('# checkout folder: $context.path_v')
|
||||||
|
@ -108,5 +104,4 @@ fn main() {
|
||||||
println(cmdres.output)
|
println(cmdres.output)
|
||||||
exit(cmdres.exit_code)
|
exit(cmdres.exit_code)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,11 +4,11 @@ import scripting
|
||||||
import vgit
|
import vgit
|
||||||
|
|
||||||
const (
|
const (
|
||||||
tool_version = '0.0.5'
|
tool_version = '0.0.5'
|
||||||
tool_description = ' Compares V executable size and performance,
|
tool_description = " Compares V executable size and performance,
|
||||||
between 2 commits from V\'s local git history.
|
between 2 commits from V\'s local git history.
|
||||||
When only one commit is given, it is compared to master.
|
When only one commit is given, it is compared to master.
|
||||||
'
|
"
|
||||||
)
|
)
|
||||||
|
|
||||||
struct Context {
|
struct Context {
|
||||||
|
@ -44,64 +44,46 @@ fn (c Context) compare_versions() {
|
||||||
c.prepare_v(c.b, c.commit_before)
|
c.prepare_v(c.b, c.commit_before)
|
||||||
c.prepare_v(c.a, c.commit_after)
|
c.prepare_v(c.a, c.commit_after)
|
||||||
scripting.chdir(c.vgo.workdir)
|
scripting.chdir(c.vgo.workdir)
|
||||||
|
|
||||||
if c.vflags.len > 0 {
|
if c.vflags.len > 0 {
|
||||||
os.setenv('VFLAGS', c.vflags, true)
|
os.setenv('VFLAGS', c.vflags, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
// The first is the baseline, against which all the others will be compared.
|
// The first is the baseline, against which all the others will be compared.
|
||||||
// It is the fastest, since hello_world.v has only a single println in it,
|
// It is the fastest, since hello_world.v has only a single println in it,
|
||||||
mut perf_files := []string{}
|
mut perf_files := []string{}
|
||||||
perf_files << c.compare_v_performance('source_hello', [
|
perf_files <<
|
||||||
'vprod @DEBUG@ -o source.c examples/hello_world.v',
|
c.compare_v_performance('source_hello', ['vprod @DEBUG@ -o source.c examples/hello_world.v', 'vprod -o source.c examples/hello_world.v', 'v @DEBUG@ -o source.c examples/hello_world.v', 'v -o source.c examples/hello_world.v'])
|
||||||
'vprod -o source.c examples/hello_world.v',
|
perf_files <<
|
||||||
'v @DEBUG@ -o source.c examples/hello_world.v',
|
c.compare_v_performance('source_v', ['vprod @DEBUG@ -o source.c @COMPILER@', 'vprod -o source.c @COMPILER@', 'v @DEBUG@ -o source.c @COMPILER@', 'v -o source.c @COMPILER@'])
|
||||||
'v -o source.c examples/hello_world.v',
|
perf_files <<
|
||||||
])
|
c.compare_v_performance('binary_hello', ['vprod -o hello examples/hello_world.v', 'v -o hello examples/hello_world.v'])
|
||||||
|
perf_files <<
|
||||||
perf_files << c.compare_v_performance('source_v', [
|
c.compare_v_performance('binary_v', ['vprod -o binary @COMPILER@', 'v -o binary @COMPILER@'])
|
||||||
'vprod @DEBUG@ -o source.c @COMPILER@',
|
|
||||||
'vprod -o source.c @COMPILER@',
|
|
||||||
'v @DEBUG@ -o source.c @COMPILER@',
|
|
||||||
'v -o source.c @COMPILER@',
|
|
||||||
])
|
|
||||||
|
|
||||||
perf_files << c.compare_v_performance('binary_hello', [
|
|
||||||
'vprod -o hello examples/hello_world.v',
|
|
||||||
'v -o hello examples/hello_world.v',
|
|
||||||
])
|
|
||||||
|
|
||||||
perf_files << c.compare_v_performance('binary_v', [
|
|
||||||
'vprod -o binary @COMPILER@',
|
|
||||||
'v -o binary @COMPILER@',
|
|
||||||
])
|
|
||||||
|
|
||||||
println('All performance files:')
|
println('All performance files:')
|
||||||
for f in perf_files {
|
for f in perf_files {
|
||||||
println(' $f')
|
println(' $f')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (c &Context) prepare_v(cdir string, commit string) {
|
fn (c &Context) prepare_v(cdir, commit string) {
|
||||||
mut cc := os.getenv('CC')
|
mut cc := os.getenv('CC')
|
||||||
if cc == '' {
|
if cc == '' {
|
||||||
cc = 'cc'
|
cc = 'cc'
|
||||||
}
|
}
|
||||||
mut vgit_context := vgit.VGitContext{
|
mut vgit_context := vgit.VGitContext{
|
||||||
cc: cc
|
cc: cc
|
||||||
commit_v: commit
|
commit_v: commit
|
||||||
path_v: cdir
|
path_v: cdir
|
||||||
path_vc: c.vc
|
path_vc: c.vc
|
||||||
workdir: c.vgo.workdir
|
workdir: c.vgo.workdir
|
||||||
v_repo_url: c.vgo.v_repo_url
|
v_repo_url: c.vgo.v_repo_url
|
||||||
vc_repo_url: c.vgo.vc_repo_url
|
vc_repo_url: c.vgo.vc_repo_url
|
||||||
}
|
}
|
||||||
vgit_context.compile_oldv_if_needed()
|
vgit_context.compile_oldv_if_needed()
|
||||||
scripting.chdir(cdir)
|
scripting.chdir(cdir)
|
||||||
println('Making a v compiler in $cdir')
|
println('Making a v compiler in $cdir')
|
||||||
scripting.run('./v -cc ${cc} -o v $vgit_context.vvlocation')
|
scripting.run('./v -cc $cc -o v $vgit_context.vvlocation')
|
||||||
println('Making a vprod compiler in $cdir')
|
println('Making a vprod compiler in $cdir')
|
||||||
scripting.run('./v -cc ${cc} -prod -o vprod $vgit_context.vvlocation')
|
scripting.run('./v -cc $cc -prod -o vprod $vgit_context.vvlocation')
|
||||||
println('Stripping and compressing cv v and vprod binaries in $cdir')
|
println('Stripping and compressing cv v and vprod binaries in $cdir')
|
||||||
scripting.run('cp cv cv_stripped')
|
scripting.run('cp cv cv_stripped')
|
||||||
scripting.run('cp v v_stripped')
|
scripting.run('cp v v_stripped')
|
||||||
|
@ -117,17 +99,19 @@ fn (c &Context) prepare_v(cdir string, commit string) {
|
||||||
scripting.show_sizes_of_files(['$cdir/v', '$cdir/v_stripped', '$cdir/v_stripped_upxed'])
|
scripting.show_sizes_of_files(['$cdir/v', '$cdir/v_stripped', '$cdir/v_stripped_upxed'])
|
||||||
scripting.show_sizes_of_files(['$cdir/vprod', '$cdir/vprod_stripped', '$cdir/vprod_stripped_upxed'])
|
scripting.show_sizes_of_files(['$cdir/vprod', '$cdir/vprod_stripped', '$cdir/vprod_stripped_upxed'])
|
||||||
vversion := scripting.run('$cdir/v -version')
|
vversion := scripting.run('$cdir/v -version')
|
||||||
vcommit := scripting.run('git rev-parse --short --verify HEAD')
|
vcommit := scripting.run('git rev-parse --short --verify HEAD')
|
||||||
println('V version is: ${vversion} , local source commit: ${vcommit}')
|
println('V version is: $vversion , local source commit: $vcommit')
|
||||||
if vgit_context.vvlocation == 'cmd/v' {
|
if vgit_context.vvlocation == 'cmd/v' {
|
||||||
if os.exists('vlib/v/ast/ast.v') {
|
if os.exists('vlib/v/ast/ast.v') {
|
||||||
println('Source lines of the compiler: ' + scripting.run('find cmd/v/ vlib/v/ -name "*.v" | grep -v /tests/ | xargs wc | tail -n -1'))
|
println('Source lines of the compiler: ' +
|
||||||
|
scripting.run('find cmd/v/ vlib/v/ -name "*.v" | grep -v /tests/ | xargs wc | tail -n -1'))
|
||||||
} else {
|
} else {
|
||||||
println('Source lines of the compiler: ' + scripting.run('wc cmd/v/*.v vlib/compiler/*.v | tail -n -1'))
|
println('Source lines of the compiler: ' +
|
||||||
|
scripting.run('wc cmd/v/*.v vlib/compiler/*.v | tail -n -1'))
|
||||||
}
|
}
|
||||||
} else if vgit_context.vvlocation == 'v.v' {
|
} else if vgit_context.vvlocation == 'v.v' {
|
||||||
println('Source lines of the compiler: ' + scripting.run('wc v.v vlib/compiler/*.v | tail -n -1'))
|
println('Source lines of the compiler: ' + scripting.run('wc v.v vlib/compiler/*.v | tail -n -1'))
|
||||||
}else{
|
} else {
|
||||||
println('Source lines of the compiler: ' + scripting.run('wc compiler/*.v | tail -n -1'))
|
println('Source lines of the compiler: ' + scripting.run('wc compiler/*.v | tail -n -1'))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -147,8 +131,8 @@ fn (c Context) compare_v_performance(label string, commands []string) string {
|
||||||
} else {
|
} else {
|
||||||
source_location_b = if os.exists('$c.b/v.v') { 'v.v ' } else { 'compiler/ ' }
|
source_location_b = if os.exists('$c.b/v.v') { 'v.v ' } else { 'compiler/ ' }
|
||||||
}
|
}
|
||||||
timestamp_a,_ := vgit.line_to_timestamp_and_commit(scripting.run('cd $c.a/ ; git rev-list -n1 --timestamp HEAD'))
|
timestamp_a, _ := vgit.line_to_timestamp_and_commit(scripting.run('cd $c.a/ ; git rev-list -n1 --timestamp HEAD'))
|
||||||
timestamp_b,_ := vgit.line_to_timestamp_and_commit(scripting.run('cd $c.b/ ; git rev-list -n1 --timestamp HEAD'))
|
timestamp_b, _ := vgit.line_to_timestamp_and_commit(scripting.run('cd $c.b/ ; git rev-list -n1 --timestamp HEAD'))
|
||||||
debug_option_a := if timestamp_a > 1570877641 { '-cg ' } else { '-debug ' }
|
debug_option_a := if timestamp_a > 1570877641 { '-cg ' } else { '-debug ' }
|
||||||
debug_option_b := if timestamp_b > 1570877641 { '-cg ' } else { '-debug ' }
|
debug_option_b := if timestamp_b > 1570877641 { '-cg ' } else { '-debug ' }
|
||||||
mut hyperfine_commands_arguments := []string{}
|
mut hyperfine_commands_arguments := []string{}
|
||||||
|
@ -156,14 +140,17 @@ fn (c Context) compare_v_performance(label string, commands []string) string {
|
||||||
println(cmd)
|
println(cmd)
|
||||||
}
|
}
|
||||||
for cmd in commands {
|
for cmd in commands {
|
||||||
hyperfine_commands_arguments << " \'cd ${c.b:-34s} ; ./$cmd \' ".replace_each(['@COMPILER@', source_location_b, '@DEBUG@', debug_option_b])
|
hyperfine_commands_arguments <<
|
||||||
|
" \'cd ${c.b:-34s} ; ./$cmd \' ".replace_each(['@COMPILER@', source_location_b, '@DEBUG@', debug_option_b])
|
||||||
}
|
}
|
||||||
for cmd in commands {
|
for cmd in commands {
|
||||||
hyperfine_commands_arguments << " \'cd ${c.a:-34s} ; ./$cmd \' ".replace_each(['@COMPILER@', source_location_a, '@DEBUG@', debug_option_a])
|
hyperfine_commands_arguments <<
|
||||||
|
" \'cd ${c.a:-34s} ; ./$cmd \' ".replace_each(['@COMPILER@', source_location_a, '@DEBUG@', debug_option_a])
|
||||||
}
|
}
|
||||||
// /////////////////////////////////////////////////////////////////////////////
|
// /////////////////////////////////////////////////////////////////////////////
|
||||||
cmd_stats_file := os.real_path([c.vgo.workdir, 'v_performance_stats_${label}.json'].join(os.path_separator))
|
cmd_stats_file := os.real_path([c.vgo.workdir, 'v_performance_stats_${label}.json'].join(os.path_separator))
|
||||||
comparison_cmd := 'hyperfine $c.hyperfineopts ' + '--export-json ${cmd_stats_file} ' + '--time-unit millisecond ' + '--style full --warmup $c.warmups ' + hyperfine_commands_arguments.join(' ')
|
comparison_cmd := 'hyperfine $c.hyperfineopts ' + '--export-json $cmd_stats_file ' + '--time-unit millisecond ' +
|
||||||
|
'--style full --warmup $c.warmups ' + hyperfine_commands_arguments.join(' ')
|
||||||
// /////////////////////////////////////////////////////////////////////////////
|
// /////////////////////////////////////////////////////////////////////////////
|
||||||
if c.vgo.verbose {
|
if c.vgo.verbose {
|
||||||
println(comparison_cmd)
|
println(comparison_cmd)
|
||||||
|
@ -175,7 +162,8 @@ fn (c Context) compare_v_performance(label string, commands []string) string {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
scripting.used_tools_must_exist(['cp', 'rm', 'strip', 'make', 'git', 'upx', 'cc', 'wc', 'tail', 'find', 'xargs', 'hyperfine'])
|
scripting.used_tools_must_exist(['cp', 'rm', 'strip', 'make', 'git', 'upx', 'cc', 'wc', 'tail',
|
||||||
|
'find', 'xargs', 'hyperfine'])
|
||||||
mut context := new_context()
|
mut context := new_context()
|
||||||
mut fp := flag.new_flag_parser(os.args)
|
mut fp := flag.new_flag_parser(os.args)
|
||||||
fp.application(os.file_name(os.executable()))
|
fp.application(os.file_name(os.executable()))
|
||||||
|
@ -184,12 +172,10 @@ fn main() {
|
||||||
fp.arguments_description('COMMIT_BEFORE [COMMIT_AFTER]')
|
fp.arguments_description('COMMIT_BEFORE [COMMIT_AFTER]')
|
||||||
fp.skip_executable()
|
fp.skip_executable()
|
||||||
fp.limit_free_args(1, 2)
|
fp.limit_free_args(1, 2)
|
||||||
|
|
||||||
context.vflags = fp.string('vflags', 0, '', 'Additional options to pass to the v commands, for example "-cc tcc"')
|
context.vflags = fp.string('vflags', 0, '', 'Additional options to pass to the v commands, for example "-cc tcc"')
|
||||||
context.hyperfineopts = fp.string('hyperfine_options', 0, '',
|
context.hyperfineopts = fp.string('hyperfine_options', 0, '', 'Additional options passed to hyperfine.
|
||||||
'Additional options passed to hyperfine.
|
|
||||||
${flag.space}For example on linux, you may want to pass:
|
${flag.space}For example on linux, you may want to pass:
|
||||||
${flag.space}--hyperfine_options "--prepare \'sync; echo 3 | sudo tee /proc/sys/vm/drop_caches\'"
|
$flag.space--hyperfine_options "--prepare \'sync; echo 3 | sudo tee /proc/sys/vm/drop_caches\'"
|
||||||
')
|
')
|
||||||
commits := vgit.add_common_tool_options(mut context.vgo, mut fp)
|
commits := vgit.add_common_tool_options(mut context.vgo, mut fp)
|
||||||
context.commit_before = commits[0]
|
context.commit_before = commits[0]
|
||||||
|
@ -204,6 +190,5 @@ ${flag.space}--hyperfine_options "--prepare \'sync; echo 3 | sudo tee /proc/sys/
|
||||||
eprintln(msg)
|
eprintln(msg)
|
||||||
exit(2)
|
exit(2)
|
||||||
}
|
}
|
||||||
|
|
||||||
context.compare_versions()
|
context.compare_versions()
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@ module main
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import term
|
import term
|
||||||
|
|
||||||
// //////////////////////////////////////////////////////////////////
|
// //////////////////////////////////////////////////////////////////
|
||||||
// / This file will get compiled as part of the main program,
|
// / This file will get compiled as part of the main program,
|
||||||
// / for a _test.v file.
|
// / for a _test.v file.
|
||||||
|
@ -14,29 +15,26 @@ import term
|
||||||
fn cb_assertion_failed(i &VAssertMetaInfo) {
|
fn cb_assertion_failed(i &VAssertMetaInfo) {
|
||||||
use_color := term.can_show_color_on_stderr()
|
use_color := term.can_show_color_on_stderr()
|
||||||
use_relative_paths := match os.getenv('VERROR_PATHS') {
|
use_relative_paths := match os.getenv('VERROR_PATHS') {
|
||||||
'absolute' {
|
'absolute' { false }
|
||||||
false
|
else { true }
|
||||||
} else {
|
|
||||||
true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
final_filename := if use_relative_paths { i.fpath } else { os.real_path(i.fpath) }
|
final_filename := if use_relative_paths { i.fpath } else { os.real_path(i.fpath) }
|
||||||
final_funcname := i.fn_name.replace('main.', '').replace('__', '.')
|
final_funcname := i.fn_name.replace('main.', '').replace('__', '.')
|
||||||
final_src := if use_color { term.bold(i.src) } else { i.src }
|
final_src := if use_color { term.bold(i.src) } else { i.src }
|
||||||
eprintln('')
|
eprintln('')
|
||||||
eprintln('$final_filename:${i.line_nr+1}: failed assert in function ${final_funcname}')
|
eprintln('$final_filename:${i.line_nr+1}: failed assert in function $final_funcname')
|
||||||
eprintln('Source : `${final_src}`')
|
eprintln('Source : `$final_src`')
|
||||||
if i.op.len > 0 && i.op != 'call' {
|
if i.op.len > 0 && i.op != 'call' {
|
||||||
mut slvalue := '${i.lvalue}'
|
mut slvalue := '$i.lvalue'
|
||||||
mut srvalue := '${i.rvalue}'
|
mut srvalue := '$i.rvalue'
|
||||||
lpostfix := if slvalue == i.llabel { '.' } else { '<= `${i.llabel}`' }
|
lpostfix := if slvalue == i.llabel { '.' } else { '<= `$i.llabel`' }
|
||||||
rpostfix := if srvalue == i.rlabel { '.' } else { '<= `${i.rlabel}`' }
|
rpostfix := if srvalue == i.rlabel { '.' } else { '<= `$i.rlabel`' }
|
||||||
if use_color {
|
if use_color {
|
||||||
slvalue = term.bold(term.yellow(slvalue))
|
slvalue = term.bold(term.yellow(slvalue))
|
||||||
srvalue = term.bold(term.yellow(srvalue))
|
srvalue = term.bold(term.yellow(srvalue))
|
||||||
}
|
}
|
||||||
eprintln(' left value: ${slvalue} ${lpostfix}')
|
eprintln(' left value: $slvalue $lpostfix')
|
||||||
eprintln(' right value: ${srvalue} ${rpostfix}')
|
eprintln(' right value: $srvalue $rpostfix')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
module main
|
module main
|
||||||
|
|
||||||
// /////////////////////////////////////////////////////////////////////
|
// /////////////////////////////////////////////////////////////////////
|
||||||
// / This file will get compiled as a part of the same module,
|
// / This file will get compiled as a part of the same module,
|
||||||
// / in which a given _test.v file is, when v is given -stats argument
|
// / in which a given _test.v file is, when v is given -stats argument
|
||||||
|
@ -77,7 +78,8 @@ fn (b &BenchedTests) fn_name() string {
|
||||||
// Called at the end of the test program produced by `v -stats file_test.v`
|
// Called at the end of the test program produced by `v -stats file_test.v`
|
||||||
fn (mut b BenchedTests) end_testing() {
|
fn (mut b BenchedTests) end_testing() {
|
||||||
b.bench.stop()
|
b.bench.stop()
|
||||||
println(inner_indent + b.bench.total_message('running V tests in "' + os.file_name(b.test_suit_file) + '"'))
|
println(inner_indent + b.bench.total_message('running V tests in "' + os.file_name(b.test_suit_file) +
|
||||||
|
'"'))
|
||||||
}
|
}
|
||||||
|
|
||||||
// ///////////////////////////////////////////////////////////////////
|
// ///////////////////////////////////////////////////////////////////
|
||||||
|
|
|
@ -5,37 +5,19 @@ import testing
|
||||||
|
|
||||||
const (
|
const (
|
||||||
known_failing_exceptions = [
|
known_failing_exceptions = [
|
||||||
'examples/vweb/vweb_example.v',
|
'vlib/v/tests/generics_test.v', // struct Repo<T, U> { => struct Repo {
|
||||||
'cmd/tools/gen_vc.v',
|
'vlib/crypto/aes/aes.v', // pub fn (c &AesCipher) encrypt(mut dst, mut src []byte) {
|
||||||
'cmd/tools/modules/vgit/vgit.v', // generics
|
'vlib/crypto/aes/block_generic.v', // fn expand_key_generic(key []byte, mut enc, mut dec []u32) {
|
||||||
'cmd/tools/preludes/live_main.v',
|
'vlib/crypto/aes/const.v', // multiple narrow columns of []string turned to 1 long single column, otherwise works
|
||||||
'cmd/tools/preludes/live_shared.v',
|
'vlib/crypto/rc4/rc4.v', // pub fn (mut c Cipher) xor_key_stream(mut dst, mut src []byte) {
|
||||||
'cmd/tools/preludes/tests_assertions.v',
|
'vlib/vweb/vweb.v', // $for method in T.methods { => $for method in T(methods) { , `return // xx` => parse expr error
|
||||||
'cmd/tools/preludes/tests_with_stats.v',
|
'vlib/v/gen/js/tests/life.v', // error: unexpected `,`, expecting ), on JS.setInterval(fn () { show(game) game = step(game) }, 500)
|
||||||
'cmd/tools/performance_compare.v', // generics
|
'vlib/builtin/js/builtin.v', // JS.console.error(s) => JS.error(s), JS.process.exit(c) => JS.exit(c)
|
||||||
'cmd/tools/oldv.v', // generics
|
'vlib/builtin/js/jsfns_node.js.v',
|
||||||
'tutorials/code/blog/article.v',
|
'vlib/builtin/js/jsfns.js.v',
|
||||||
'tutorials/code/blog/blog.v',
|
'vlib/builtin/js/jsfns_browser.js.v',
|
||||||
'vlib/arrays/arrays.v',
|
'vlib/builtin/bare/linuxsys_bare.v', // error: expr(): bad token `asm`, on `asm {}`
|
||||||
'vlib/arrays/arrays_test.v',
|
'vlib/os/os.v', // embeded comments, mib := [1/* CTL_KERN */, 14/* KERN_PROC */, 12/* KERN_PROC_PATHNAME */, -1] => comment the rest of the line
|
||||||
'vlib/builtin/js/hashmap.v',
|
|
||||||
'vlib/v/tests/fn_variadic_test.v',
|
|
||||||
'vlib/v/tests/generic_test.v',
|
|
||||||
'vlib/crypto/aes/aes.v',
|
|
||||||
'vlib/crypto/aes/aes_cbc.v',
|
|
||||||
'vlib/crypto/aes/block_generic.v',
|
|
||||||
'vlib/crypto/aes/const.v',
|
|
||||||
'vlib/crypto/aes/cypher_generic.v',
|
|
||||||
'vlib/crypto/rc4/rc4.v',
|
|
||||||
'vlib/eventbus/eventbus_test.v',
|
|
||||||
'vlib/os/bare/bare_example_linux.v',
|
|
||||||
'vlib/szip/szip.v',
|
|
||||||
'vlib/uiold/examples/users_gui/users.v',
|
|
||||||
'vlib/vweb/assets/assets.v',
|
|
||||||
'vlib/vweb/vweb.v',
|
|
||||||
'vlib/v/gen/js/tests/life.v',
|
|
||||||
'vlib/builtin/bare/linuxsys_bare.v',
|
|
||||||
'vlib/os/os.v',
|
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,7 @@ const (
|
||||||
struct App {
|
struct App {
|
||||||
pub mut:
|
pub mut:
|
||||||
vweb vweb.Context // TODO embed
|
vweb vweb.Context // TODO embed
|
||||||
cnt int
|
cnt int
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
@ -31,9 +31,9 @@ pub fn (mut app App) json_endpoint() vweb.Result {
|
||||||
pub fn (mut app App) index() vweb.Result {
|
pub fn (mut app App) index() vweb.Result {
|
||||||
app.cnt++
|
app.cnt++
|
||||||
show := true
|
show := true
|
||||||
//app.vweb.text('Hello world from vweb')
|
// app.vweb.text('Hello world from vweb')
|
||||||
hello := 'Hello world from vweb'
|
hello := 'Hello world from vweb'
|
||||||
numbers := [1,2,3]
|
numbers := [1, 2, 3]
|
||||||
return $vweb.html()
|
return $vweb.html()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -42,6 +42,9 @@ pub fn (mut app App) text() vweb.Result {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (mut app App) cookie() vweb.Result {
|
pub fn (mut app App) cookie() vweb.Result {
|
||||||
app.vweb.set_cookie(name:'cookie', value:'test')
|
app.vweb.set_cookie({
|
||||||
|
name: 'cookie'
|
||||||
|
value: 'test'
|
||||||
|
})
|
||||||
return app.vweb.text('Headers: $app.vweb.headers')
|
return app.vweb.text('Headers: $app.vweb.headers')
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,7 +26,6 @@ pub fn (app &App) index_html() vweb.Result {
|
||||||
return $vweb.html()
|
return $vweb.html()
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
pub fn (app &App) index() vweb.Result {
|
pub fn (app &App) index() vweb.Result {
|
||||||
articles := app.find_all_articles()
|
articles := app.find_all_articles()
|
||||||
return $vweb.html()
|
return $vweb.html()
|
||||||
|
@ -53,7 +52,7 @@ pub fn (mut app App) new_article() vweb.Result {
|
||||||
app.vweb.text('Empty text/title')
|
app.vweb.text('Empty text/title')
|
||||||
return vweb.Result{}
|
return vweb.Result{}
|
||||||
}
|
}
|
||||||
article := Article {
|
article := Article{
|
||||||
title: title
|
title: title
|
||||||
text: text
|
text: text
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,15 +5,16 @@ module arrays
|
||||||
// - idx_min / idx_max - return the index of the first minumum / maximum
|
// - idx_min / idx_max - return the index of the first minumum / maximum
|
||||||
// - shuffle - randomize array items order in place (allowing exit after n items)
|
// - shuffle - randomize array items order in place (allowing exit after n items)
|
||||||
// - merge - combine two sorted arrays and maintain sorted order
|
// - merge - combine two sorted arrays and maintain sorted order
|
||||||
|
|
||||||
import rand
|
import rand
|
||||||
|
|
||||||
// min returns the minimum
|
// min returns the minimum
|
||||||
[direct_array_access]
|
[direct_array_access]
|
||||||
pub fn min<T>(a []T) T {
|
pub fn min<T>(a []T) T {
|
||||||
if a.len==0 { panic('.min called on an empty array') }
|
if a.len == 0 {
|
||||||
|
panic('.min called on an empty array')
|
||||||
|
}
|
||||||
mut val := a[0]
|
mut val := a[0]
|
||||||
for i in 0..a.len {
|
for i in 0 .. a.len {
|
||||||
if a[i] < val {
|
if a[i] < val {
|
||||||
val = a[i]
|
val = a[i]
|
||||||
}
|
}
|
||||||
|
@ -24,9 +25,11 @@ pub fn min<T>(a []T) T {
|
||||||
// max returns the maximum
|
// max returns the maximum
|
||||||
[direct_array_access]
|
[direct_array_access]
|
||||||
pub fn max<T>(a []T) T {
|
pub fn max<T>(a []T) T {
|
||||||
if a.len==0 { panic('.max called on an empty array') }
|
if a.len == 0 {
|
||||||
|
panic('.max called on an empty array')
|
||||||
|
}
|
||||||
mut val := a[0]
|
mut val := a[0]
|
||||||
for i in 0..a.len {
|
for i in 0 .. a.len {
|
||||||
if a[i] > val {
|
if a[i] > val {
|
||||||
val = a[i]
|
val = a[i]
|
||||||
}
|
}
|
||||||
|
@ -37,10 +40,12 @@ pub fn max<T>(a []T) T {
|
||||||
// idx_min returns the index of the first minimum
|
// idx_min returns the index of the first minimum
|
||||||
[direct_array_access]
|
[direct_array_access]
|
||||||
pub fn idx_min<T>(a []T) int {
|
pub fn idx_min<T>(a []T) int {
|
||||||
if a.len==0 { panic('.idxmin called on an empty array') }
|
if a.len == 0 {
|
||||||
|
panic('.idxmin called on an empty array')
|
||||||
|
}
|
||||||
mut idx := 0
|
mut idx := 0
|
||||||
mut val := a[0]
|
mut val := a[0]
|
||||||
for i in 0..a.len {
|
for i in 0 .. a.len {
|
||||||
if a[i] < val {
|
if a[i] < val {
|
||||||
val = a[i]
|
val = a[i]
|
||||||
idx = i
|
idx = i
|
||||||
|
@ -52,10 +57,12 @@ pub fn idx_min<T>(a []T) int {
|
||||||
// idx_max returns the index of the first maximum
|
// idx_max returns the index of the first maximum
|
||||||
[direct_array_access]
|
[direct_array_access]
|
||||||
pub fn idx_max<T>(a []T) int {
|
pub fn idx_max<T>(a []T) int {
|
||||||
if a.len==0 { panic('.idxmax called on an empty array') }
|
if a.len == 0 {
|
||||||
|
panic('.idxmax called on an empty array')
|
||||||
|
}
|
||||||
mut idx := 0
|
mut idx := 0
|
||||||
mut val := a[0]
|
mut val := a[0]
|
||||||
for i in 0..a.len {
|
for i in 0 .. a.len {
|
||||||
if a[i] > val {
|
if a[i] > val {
|
||||||
val = a[i]
|
val = a[i]
|
||||||
idx = i
|
idx = i
|
||||||
|
@ -67,10 +74,12 @@ pub fn idx_max<T>(a []T) int {
|
||||||
// shuffle randomizes the first n items of an array in place (all if n=0)
|
// shuffle randomizes the first n items of an array in place (all if n=0)
|
||||||
[direct_array_access]
|
[direct_array_access]
|
||||||
pub fn shuffle<T>(mut a []T, n int) {
|
pub fn shuffle<T>(mut a []T, n int) {
|
||||||
if n < 0 || n > a.len { panic("shuffle's argument 'n' must be in range [0,a.len]") }
|
if n < 0 || n > a.len {
|
||||||
cnt := if n==0 { a.len-1 } else { n }
|
panic("shuffle's argument 'n' must be in range [0,a.len]")
|
||||||
for i in 0..cnt {
|
}
|
||||||
x := rand.int_in_range(i,a.len)
|
cnt := if n == 0 { a.len - 1 } else { n }
|
||||||
|
for i in 0 .. cnt {
|
||||||
|
x := rand.int_in_range(i, a.len)
|
||||||
// swap
|
// swap
|
||||||
a_i := a[i]
|
a_i := a[i]
|
||||||
a[i] = a[x]
|
a[i] = a[x]
|
||||||
|
@ -78,17 +87,15 @@ pub fn shuffle<T>(mut a []T, n int) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// merge two sorted arrays (ascending) and maintain sorted order
|
// merge two sorted arrays (ascending) and maintain sorted order
|
||||||
[direct_array_access]
|
[direct_array_access]
|
||||||
pub fn merge<T>(a []T, b []T) []T {
|
pub fn merge<T>(a, b []T) []T {
|
||||||
mut m := []T{len:a.len + b.len}
|
mut m := []T{len: a.len + b.len}
|
||||||
mut ia := 0
|
mut ia := 0
|
||||||
mut ib := 0
|
mut ib := 0
|
||||||
mut j := 0
|
mut j := 0
|
||||||
|
|
||||||
// TODO efficient approach to merge_desc where: a[ia] >= b[ib]
|
// TODO efficient approach to merge_desc where: a[ia] >= b[ib]
|
||||||
for ia<a.len && ib<b.len {
|
for ia < a.len && ib < b.len {
|
||||||
if a[ia] <= b[ib] {
|
if a[ia] <= b[ib] {
|
||||||
m[j] = a[ia]
|
m[j] = a[ia]
|
||||||
ia++
|
ia++
|
||||||
|
@ -98,21 +105,17 @@ pub fn merge<T>(a []T, b []T) []T {
|
||||||
}
|
}
|
||||||
j++
|
j++
|
||||||
}
|
}
|
||||||
|
|
||||||
// a leftovers
|
// a leftovers
|
||||||
for ia < a.len {
|
for ia < a.len {
|
||||||
m[j] = a[ia]
|
m[j] = a[ia]
|
||||||
ia++
|
ia++
|
||||||
j++
|
j++
|
||||||
}
|
}
|
||||||
|
|
||||||
// b leftovers
|
// b leftovers
|
||||||
for ib < b.len {
|
for ib < b.len {
|
||||||
m[j] = b[ib]
|
m[j] = b[ib]
|
||||||
ib++
|
ib++
|
||||||
j++
|
j++
|
||||||
}
|
}
|
||||||
|
|
||||||
return m
|
return m
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,94 +4,78 @@ import rand
|
||||||
|
|
||||||
fn test_min() {
|
fn test_min() {
|
||||||
a := [8, 2, 6, 4]
|
a := [8, 2, 6, 4]
|
||||||
assert min<int>(a)==2
|
assert min<int>(a) == 2
|
||||||
assert min<int>(a[2..])==4
|
assert min<int>(a[2..]) == 4
|
||||||
|
|
||||||
b := [f32(5.1), 3.1, 1.1, 9.1]
|
b := [f32(5.1), 3.1, 1.1, 9.1]
|
||||||
assert min<f32>(b) == f32(1.1)
|
assert min<f32>(b) == f32(1.1)
|
||||||
assert min<f32>(b[..2]) == f32(3.1)
|
assert min<f32>(b[..2]) == f32(3.1)
|
||||||
|
|
||||||
c := [byte(4), 9, 3, 1]
|
c := [byte(4), 9, 3, 1]
|
||||||
assert min<byte>(c) == byte(1)
|
assert min<byte>(c) == byte(1)
|
||||||
assert min<byte>(c[..3]) == byte(3)
|
assert min<byte>(c[..3]) == byte(3)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fn test_max() {
|
fn test_max() {
|
||||||
a := [8, 2, 6, 4]
|
a := [8, 2, 6, 4]
|
||||||
assert max<int>(a)==8
|
assert max<int>(a) == 8
|
||||||
assert max<int>(a[1..])==6
|
assert max<int>(a[1..]) == 6
|
||||||
|
|
||||||
b := [f32(5.1), 3.1, 1.1, 9.1]
|
b := [f32(5.1), 3.1, 1.1, 9.1]
|
||||||
assert max<f32>(b) == f32(9.1)
|
assert max<f32>(b) == f32(9.1)
|
||||||
assert max<f32>(b[..3]) == f32(5.1)
|
assert max<f32>(b[..3]) == f32(5.1)
|
||||||
|
|
||||||
c := [byte(4), 9, 3, 1]
|
c := [byte(4), 9, 3, 1]
|
||||||
assert max<byte>(c) == byte(9)
|
assert max<byte>(c) == byte(9)
|
||||||
assert max<byte>(c[2..]) == byte(3)
|
assert max<byte>(c[2..]) == byte(3)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fn test_idx_min() {
|
fn test_idx_min() {
|
||||||
a := [8, 2, 6, 4]
|
a := [8, 2, 6, 4]
|
||||||
assert idx_min<int>(a)==1
|
assert idx_min<int>(a) == 1
|
||||||
|
|
||||||
b := [f32(5.1), 3.1, 1.1, 9.1]
|
b := [f32(5.1), 3.1, 1.1, 9.1]
|
||||||
assert idx_min<f32>(b) == 2
|
assert idx_min<f32>(b) == 2
|
||||||
|
|
||||||
c := [byte(4), 9, 3, 1]
|
c := [byte(4), 9, 3, 1]
|
||||||
assert idx_min<byte>(c) == 3
|
assert idx_min<byte>(c) == 3
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fn test_idx_max() {
|
fn test_idx_max() {
|
||||||
a := [8, 2, 6, 4]
|
a := [8, 2, 6, 4]
|
||||||
assert idx_max<int>(a)==0
|
assert idx_max<int>(a) == 0
|
||||||
|
|
||||||
b := [f32(5.1), 3.1, 1.1, 9.1]
|
b := [f32(5.1), 3.1, 1.1, 9.1]
|
||||||
assert idx_max<f32>(b) == 3
|
assert idx_max<f32>(b) == 3
|
||||||
|
|
||||||
c := [byte(4), 9, 3, 1]
|
c := [byte(4), 9, 3, 1]
|
||||||
assert idx_max<byte>(c) == 1
|
assert idx_max<byte>(c) == 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fn test_shuffle() {
|
fn test_shuffle() {
|
||||||
rand.seed([u32(1),2]) // set seed to produce same results in order
|
rand.seed([u32(1), 2]) // set seed to produce same results in order
|
||||||
|
a := [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
|
||||||
a := [1,2,3,4,5,6,7,8,9,10]
|
|
||||||
mut b := a.clone()
|
mut b := a.clone()
|
||||||
mut c := a.clone()
|
mut c := a.clone()
|
||||||
shuffle<int>(mut b, 0)
|
shuffle<int>(mut b, 0)
|
||||||
shuffle<int>(mut c, 0)
|
shuffle<int>(mut c, 0)
|
||||||
assert b == [6, 4, 5, 1, 9, 2, 10, 3, 8, 7]
|
assert b == [6, 4, 5, 1, 9, 2, 10, 3, 8, 7]
|
||||||
assert c == [1, 6, 5, 8, 7, 2, 10, 9, 3, 4]
|
assert c == [1, 6, 5, 8, 7, 2, 10, 9, 3, 4]
|
||||||
|
|
||||||
// test shuffling a slice
|
// test shuffling a slice
|
||||||
mut d := a.clone()
|
mut d := a.clone()
|
||||||
shuffle<int>(mut d[..5], 0)
|
shuffle<int>(mut d[..5], 0)
|
||||||
assert d == [5, 2, 1, 3, 4, 6, 7, 8, 9, 10]
|
assert d == [5, 2, 1, 3, 4, 6, 7, 8, 9, 10]
|
||||||
assert d[5..] == a[5..]
|
assert d[5..] == a[5..]
|
||||||
|
|
||||||
// test shuffling n items
|
// test shuffling n items
|
||||||
mut e := a.clone()
|
mut e := a.clone()
|
||||||
shuffle<int>(mut e, 5)
|
shuffle<int>(mut e, 5)
|
||||||
assert e[..5] == [10, 3, 1, 8, 4]
|
assert e[..5] == [10, 3, 1, 8, 4]
|
||||||
assert e[5..] == [6, 7, 5, 9, 2]
|
assert e[5..] == [6, 7, 5, 9, 2]
|
||||||
|
|
||||||
// test shuffling empty array
|
// test shuffling empty array
|
||||||
mut f := a[..0]
|
mut f := a[..0]
|
||||||
shuffle<int>(mut f,0)
|
shuffle<int>(mut f, 0)
|
||||||
assert f == []int{}
|
assert f == []int{}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_merge() {
|
fn test_merge() {
|
||||||
a := [1,3,5,5,7]
|
a := [1, 3, 5, 5, 7]
|
||||||
b := [2,4,4,5,6,8]
|
b := [2, 4, 4, 5, 6, 8]
|
||||||
c := []int{}
|
c := []int{}
|
||||||
d := []int{}
|
d := []int{}
|
||||||
assert merge<int>(a,b) == [1,2,3,4,4,5,5,5,6,7,8]
|
assert merge<int>(a, b) == [1, 2, 3, 4, 4, 5, 5, 5, 6, 7, 8]
|
||||||
assert merge<int>(c,d) == []
|
assert merge<int>(c, d) == []
|
||||||
assert merge<int>(a,c) == a
|
assert merge<int>(a, c) == a
|
||||||
assert merge<int>(d,b) == b
|
assert merge<int>(d, b) == b
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,16 +1,11 @@
|
||||||
// Copyright (c) 2019-2020 Alexander Medvednikov. All rights reserved.
|
// Copyright (c) 2019-2020 Alexander Medvednikov. All rights reserved.
|
||||||
// Use of this source code is governed by an MIT license
|
// Use of this source code is governed by an MIT license
|
||||||
// that can be found in the LICENSE file.
|
// that can be found in the LICENSE file.
|
||||||
|
|
||||||
// Cipher block chaining (CBC) mode.
|
// Cipher block chaining (CBC) mode.
|
||||||
|
|
||||||
// CBC provides confidentiality by xoring (chaining) each plaintext block
|
// CBC provides confidentiality by xoring (chaining) each plaintext block
|
||||||
// with the previous ciphertext block before applying the block cipher.
|
// with the previous ciphertext block before applying the block cipher.
|
||||||
|
|
||||||
// See NIST SP 800-38A, pp 10-11
|
// See NIST SP 800-38A, pp 10-11
|
||||||
|
|
||||||
// NOTE this will be moved to crypto.cipher interface (joe-c)
|
// NOTE this will be moved to crypto.cipher interface (joe-c)
|
||||||
|
|
||||||
module aes
|
module aes
|
||||||
|
|
||||||
import crypto.cipher
|
import crypto.cipher
|
||||||
|
@ -27,10 +22,10 @@ mut:
|
||||||
// internal
|
// internal
|
||||||
fn new_aes_cbc(b AesCipher, iv []byte) AesCbc {
|
fn new_aes_cbc(b AesCipher, iv []byte) AesCbc {
|
||||||
return AesCbc{
|
return AesCbc{
|
||||||
b: b,
|
b: b
|
||||||
block_size: b.block_size(),
|
block_size: b.block_size()
|
||||||
iv: iv.clone(),
|
iv: iv.clone()
|
||||||
tmp: []byte{len:(b.block_size()),}
|
tmp: []byte{len: (b.block_size())}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -44,12 +39,14 @@ pub fn new_cbc(b AesCipher, iv []byte) AesCbc {
|
||||||
return new_aes_cbc(b, iv)
|
return new_aes_cbc(b, iv)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (x &AesCbc) block_size() int { return x.block_size }
|
pub fn (x &AesCbc) block_size() int {
|
||||||
|
return x.block_size
|
||||||
|
}
|
||||||
|
|
||||||
pub fn (x &AesCbc) encrypt_blocks(mut dst_ []byte, src_ []byte) {
|
pub fn (x &AesCbc) encrypt_blocks(mut dst_ []byte, src_ []byte) {
|
||||||
mut dst := *dst_
|
mut dst := *dst_
|
||||||
mut src := src_
|
mut src := src_
|
||||||
if src.len%x.block_size != 0 {
|
if src.len % x.block_size != 0 {
|
||||||
panic('crypto.cipher: input not full blocks')
|
panic('crypto.cipher: input not full blocks')
|
||||||
}
|
}
|
||||||
if dst.len < src.len {
|
if dst.len < src.len {
|
||||||
|
@ -58,14 +55,11 @@ pub fn (x &AesCbc) encrypt_blocks(mut dst_ []byte, src_ []byte) {
|
||||||
if subtle.inexact_overlap(dst[..src.len], src_) {
|
if subtle.inexact_overlap(dst[..src.len], src_) {
|
||||||
panic('crypto.cipher: invalid buffer overlap')
|
panic('crypto.cipher: invalid buffer overlap')
|
||||||
}
|
}
|
||||||
|
|
||||||
mut iv := x.iv
|
mut iv := x.iv
|
||||||
|
|
||||||
for src.len > 0 {
|
for src.len > 0 {
|
||||||
// Write the xor to dst, then encrypt in place.
|
// Write the xor to dst, then encrypt in place.
|
||||||
cipher.xor_bytes(mut dst[..x.block_size], src[..x.block_size], iv)
|
cipher.xor_bytes(mut dst[..x.block_size], src[..x.block_size], iv)
|
||||||
x.b.encrypt(mut dst[..x.block_size], mut dst[..x.block_size])
|
x.b.encrypt(mut dst[..x.block_size], mut dst[..x.block_size])
|
||||||
|
|
||||||
// Move to the next block with this block as the next iv.
|
// Move to the next block with this block as the next iv.
|
||||||
iv = dst[..x.block_size]
|
iv = dst[..x.block_size]
|
||||||
if x.block_size >= src.len {
|
if x.block_size >= src.len {
|
||||||
|
@ -75,13 +69,12 @@ pub fn (x &AesCbc) encrypt_blocks(mut dst_ []byte, src_ []byte) {
|
||||||
}
|
}
|
||||||
dst = dst[x.block_size..]
|
dst = dst[x.block_size..]
|
||||||
}
|
}
|
||||||
|
|
||||||
// Save the iv for the next crypt_blocks call.
|
// Save the iv for the next crypt_blocks call.
|
||||||
copy(x.iv, iv)
|
copy(x.iv, iv)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (mut x AesCbc) decrypt_blocks(mut dst []byte, src []byte) {
|
pub fn (mut x AesCbc) decrypt_blocks(mut dst []byte, src []byte) {
|
||||||
if src.len%x.block_size != 0 {
|
if src.len % x.block_size != 0 {
|
||||||
panic('crypto.cipher: input not full blocks')
|
panic('crypto.cipher: input not full blocks')
|
||||||
}
|
}
|
||||||
if dst.len < src.len {
|
if dst.len < src.len {
|
||||||
|
@ -93,33 +86,27 @@ pub fn (mut x AesCbc) decrypt_blocks(mut dst []byte, src []byte) {
|
||||||
if src.len == 0 {
|
if src.len == 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// For each block, we need to xor the decrypted data with the previous block's ciphertext (the iv).
|
// For each block, we need to xor the decrypted data with the previous block's ciphertext (the iv).
|
||||||
// To avoid making a copy each time, we loop over the blocks BACKWARDS.
|
// To avoid making a copy each time, we loop over the blocks BACKWARDS.
|
||||||
mut end := src.len
|
mut end := src.len
|
||||||
mut start := end - x.block_size
|
mut start := end - x.block_size
|
||||||
mut prev := start - x.block_size
|
mut prev := start - x.block_size
|
||||||
|
|
||||||
// Copy the last block of ciphertext in preparation as the new iv.
|
// Copy the last block of ciphertext in preparation as the new iv.
|
||||||
copy(x.tmp, src.slice(start, end))
|
copy(x.tmp, src.slice(start, end))
|
||||||
|
|
||||||
// Loop over all but the first block.
|
// Loop over all but the first block.
|
||||||
for start > 0 {
|
for start > 0 {
|
||||||
mut src_chunk := src.slice(start, end)
|
mut src_chunk := src.slice(start, end)
|
||||||
x.b.decrypt(mut (*dst).slice(start, end), mut src_chunk)
|
x.b.decrypt(mut (*dst).slice(start, end), mut src_chunk)
|
||||||
cipher.xor_bytes(mut (*dst).slice(start, end), (*dst).slice(start, end), src.slice(prev, start))
|
cipher.xor_bytes(mut (*dst).slice(start, end), (*dst).slice(start, end), src.slice(prev,
|
||||||
|
start))
|
||||||
end = start
|
end = start
|
||||||
start = prev
|
start = prev
|
||||||
prev -= x.block_size
|
prev -= x.block_size
|
||||||
}
|
}
|
||||||
|
|
||||||
// The first block is special because it uses the saved iv.
|
// The first block is special because it uses the saved iv.
|
||||||
mut src_chunk := src.slice(start, end)
|
mut src_chunk := src.slice(start, end)
|
||||||
x.b.decrypt(mut (*dst).slice(start, end), mut src_chunk)
|
x.b.decrypt(mut (*dst).slice(start, end), mut src_chunk)
|
||||||
cipher.xor_bytes(mut (*dst).slice(start, end), (*dst).slice(start, end), x.iv)
|
cipher.xor_bytes(mut (*dst).slice(start, end), (*dst).slice(start, end), x.iv)
|
||||||
|
|
||||||
|
|
||||||
// Set the new iv to the first block we copied earlier.
|
// Set the new iv to the first block we copied earlier.
|
||||||
x.iv = x.tmp
|
x.iv = x.tmp
|
||||||
x.tmp = x.iv
|
x.tmp = x.iv
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
// Copyright (c) 2019-2020 Alexander Medvednikov. All rights reserved.
|
// Copyright (c) 2019-2020 Alexander Medvednikov. All rights reserved.
|
||||||
// Use of this source code is governed by an MIT license
|
// Use of this source code is governed by an MIT license
|
||||||
// that can be found in the LICENSE file.
|
// that can be found in the LICENSE file.
|
||||||
|
|
||||||
import crypto.aes
|
import crypto.aes
|
||||||
|
|
||||||
fn test_crypto_aes() {
|
fn test_crypto_aes() {
|
||||||
|
@ -17,12 +16,12 @@ fn test_crypto_aes() {
|
||||||
iv := ciphertext[..aes.block_size]
|
iv := ciphertext[..aes.block_size]
|
||||||
ciphertext = ciphertext[aes.block_size..]
|
ciphertext = ciphertext[aes.block_size..]
|
||||||
// CBC mode always works in whole blocks.
|
// CBC mode always works in whole blocks.
|
||||||
if ciphertext.len%aes.block_size != 0 {
|
if ciphertext.len % aes.block_size != 0 {
|
||||||
panic('ciphertext is not a multiple of the block size')
|
panic('ciphertext is not a multiple of the block size')
|
||||||
}
|
}
|
||||||
mode := aes.new_cbc(block, iv)
|
mode := aes.new_cbc(block, iv)
|
||||||
cipher_clone := ciphertext.clone()
|
cipher_clone := ciphertext.clone()
|
||||||
mode.encrypt_blocks(mut ciphertext, cipher_clone)
|
mode.encrypt_blocks(mut ciphertext, cipher_clone)
|
||||||
|
assert ciphertext.hex() ==
|
||||||
assert ciphertext.hex() == 'c210459b514668ddc44674885e4979215265a6c44431a248421254ef357a8c2a308a8bddf5623af9df91737562041cf1'
|
'c210459b514668ddc44674885e4979215265a6c44431a248421254ef357a8c2a308a8bddf5623af9df91737562041cf1'
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
// Copyright (c) 2019-2020 Alexander Medvednikov. All rights reserved.
|
// Copyright (c) 2019-2020 Alexander Medvednikov. All rights reserved.
|
||||||
// Use of this source code is governed by an MIT license
|
// Use of this source code is governed by an MIT license
|
||||||
// that can be found in the LICENSE file.
|
// that can be found in the LICENSE file.
|
||||||
|
|
||||||
module aes
|
module aes
|
||||||
|
|
||||||
// new_cipher_generic creates and returns a new cipher.Block
|
// new_cipher_generic creates and returns a new cipher.Block
|
||||||
|
@ -9,8 +8,8 @@ module aes
|
||||||
fn new_cipher_generic(key []byte) AesCipher {
|
fn new_cipher_generic(key []byte) AesCipher {
|
||||||
n := key.len + 28
|
n := key.len + 28
|
||||||
mut c := AesCipher{
|
mut c := AesCipher{
|
||||||
enc: []u32{len:(n)}
|
enc: []u32{len: (n)}
|
||||||
dec: []u32{len:(n)}
|
dec: []u32{len: (n)}
|
||||||
}
|
}
|
||||||
expand_key_generic(key, mut c.enc, mut c.dec)
|
expand_key_generic(key, mut c.enc, mut c.dec)
|
||||||
return c
|
return c
|
||||||
|
|
|
@ -1,35 +1,28 @@
|
||||||
import eventbus
|
import eventbus
|
||||||
|
|
||||||
struct EventData {
|
struct EventData {
|
||||||
data string
|
data string
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_eventbus(){
|
fn test_eventbus() {
|
||||||
ev_data := &EventData{'hello'}
|
ev_data := &EventData{'hello'}
|
||||||
mut eb := eventbus.new()
|
mut eb := eventbus.new()
|
||||||
eb.subscriber.subscribe_once("on_test", on_test)
|
eb.subscriber.subscribe_once('on_test', on_test)
|
||||||
|
assert eb.has_subscriber('on_test')
|
||||||
assert eb.has_subscriber("on_test")
|
assert eb.subscriber.is_subscribed('on_test')
|
||||||
assert eb.subscriber.is_subscribed("on_test")
|
eb.publish('on_test', eb, ev_data)
|
||||||
|
assert !eb.has_subscriber('on_test')
|
||||||
eb.publish("on_test", eb, ev_data)
|
assert !eb.subscriber.is_subscribed('on_test')
|
||||||
|
eb.subscriber.subscribe('on_test', on_test)
|
||||||
assert !eb.has_subscriber("on_test")
|
assert eb.has_subscriber('on_test')
|
||||||
assert !eb.subscriber.is_subscribed("on_test")
|
assert eb.subscriber.is_subscribed('on_test')
|
||||||
|
|
||||||
eb.subscriber.subscribe("on_test", on_test)
|
|
||||||
|
|
||||||
assert eb.has_subscriber("on_test")
|
|
||||||
assert eb.subscriber.is_subscribed("on_test")
|
|
||||||
|
|
||||||
eb.clear_all()
|
eb.clear_all()
|
||||||
|
assert !eb.has_subscriber('on_test')
|
||||||
assert !eb.has_subscriber("on_test")
|
assert !eb.subscriber.is_subscribed('on_test')
|
||||||
assert !eb.subscriber.is_subscribed("on_test")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_test(receiver voidptr, ev &EventData, sender voidptr) {
|
fn on_test(receiver voidptr, ev &EventData, sender voidptr) {
|
||||||
assert receiver == 0
|
assert receiver == 0
|
||||||
assert sender != 0
|
assert sender != 0
|
||||||
assert ev.data == "hello"
|
assert ev.data == 'hello'
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,5 +3,5 @@ fn main() {
|
||||||
s := 'test string\n'
|
s := 'test string\n'
|
||||||
sys_write(1, s.str, u64(s.len))
|
sys_write(1, s.str, u64(s.len))
|
||||||
a := s[0]
|
a := s[0]
|
||||||
println("Hello freestanding!")
|
println('Hello freestanding!')
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,24 +3,37 @@ module szip
|
||||||
#flag -I @VROOT/thirdparty/zip
|
#flag -I @VROOT/thirdparty/zip
|
||||||
#include "zip.c"
|
#include "zip.c"
|
||||||
#include "zip.h"
|
#include "zip.h"
|
||||||
|
struct C.zip_t {
|
||||||
struct C.zip_t {}
|
}
|
||||||
|
|
||||||
type Zip = C.zip_t
|
type Zip = C.zip_t
|
||||||
|
|
||||||
fn C.zip_open(byteptr, int, byte) &Zip
|
fn C.zip_open(byteptr, int, byte) &Zip
|
||||||
|
|
||||||
fn C.zip_close(&Zip)
|
fn C.zip_close(&Zip)
|
||||||
|
|
||||||
fn C.zip_entry_open(&Zip, byteptr) int
|
fn C.zip_entry_open(&Zip, byteptr) int
|
||||||
|
|
||||||
fn C.zip_entry_close(&Zip) int
|
fn C.zip_entry_close(&Zip) int
|
||||||
|
|
||||||
fn C.zip_entry_name(&Zip) byteptr
|
fn C.zip_entry_name(&Zip) byteptr
|
||||||
|
|
||||||
fn C.zip_entry_index(&Zip) int
|
fn C.zip_entry_index(&Zip) int
|
||||||
|
|
||||||
fn C.zip_entry_isdir(&Zip) int
|
fn C.zip_entry_isdir(&Zip) int
|
||||||
|
|
||||||
fn C.zip_entry_size(&Zip) u64
|
fn C.zip_entry_size(&Zip) u64
|
||||||
|
|
||||||
fn C.zip_entry_crc32(&Zip) u32
|
fn C.zip_entry_crc32(&Zip) u32
|
||||||
|
|
||||||
fn C.zip_entry_write(&Zip, voidptr, int) int
|
fn C.zip_entry_write(&Zip, voidptr, int) int
|
||||||
|
|
||||||
fn C.zip_entry_fwrite(&Zip, byteptr) int
|
fn C.zip_entry_fwrite(&Zip, byteptr) int
|
||||||
|
|
||||||
fn C.zip_entry_read(&Zip, byteptr, int) int
|
fn C.zip_entry_read(&Zip, byteptr, int) int
|
||||||
|
|
||||||
fn C.zip_entry_fread(&Zip, byteptr) int
|
fn C.zip_entry_fread(&Zip, byteptr) int
|
||||||
|
|
||||||
fn C.zip_total_entries(&Zip) int
|
fn C.zip_total_entries(&Zip) int
|
||||||
|
|
||||||
// Ref - miniz.h
|
// Ref - miniz.h
|
||||||
|
|
|
@ -64,7 +64,8 @@ fn test_variadic_only_with_no_vargs() {
|
||||||
fn_variadic_only_with_no_vargs()
|
fn_variadic_only_with_no_vargs()
|
||||||
}
|
}
|
||||||
|
|
||||||
struct VaTestStruct {}
|
struct VaTestStruct {
|
||||||
|
}
|
||||||
|
|
||||||
fn (a VaTestStruct) variadic_method(name string, groups ...VaTestGroup) {
|
fn (a VaTestStruct) variadic_method(name string, groups ...VaTestGroup) {
|
||||||
assert groups.len == 2
|
assert groups.len == 2
|
||||||
|
|
|
@ -2,7 +2,6 @@ module assets
|
||||||
|
|
||||||
// this module provides an AssetManager for combining
|
// this module provides an AssetManager for combining
|
||||||
// and caching javascript & css.
|
// and caching javascript & css.
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import time
|
import time
|
||||||
import crypto.md5
|
import crypto.md5
|
||||||
|
@ -101,7 +100,9 @@ fn (am AssetManager) combine(asset_type string, to_file bool) string {
|
||||||
return out
|
return out
|
||||||
}
|
}
|
||||||
if !os.is_dir(am.cache_dir) {
|
if !os.is_dir(am.cache_dir) {
|
||||||
os.mkdir(am.cache_dir) or { panic(err) }
|
os.mkdir(am.cache_dir) or {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
mut file := os.create(out_file) or {
|
mut file := os.create(out_file) or {
|
||||||
panic(err)
|
panic(err)
|
||||||
|
@ -157,7 +158,9 @@ fn (mut am AssetManager) add(asset_type, file string) bool {
|
||||||
}
|
}
|
||||||
asset := Asset{
|
asset := Asset{
|
||||||
file_path: file
|
file_path: file
|
||||||
last_modified: time.Time{unix: u64(os.file_last_mod_unix(file))}
|
last_modified: time.Time{
|
||||||
|
unix: u64(os.file_last_mod_unix(file))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if asset_type == 'css' {
|
if asset_type == 'css' {
|
||||||
am.css << asset
|
am.css << asset
|
||||||
|
@ -183,11 +186,7 @@ fn (am AssetManager) get_assets(asset_type string) []Asset {
|
||||||
if asset_type != 'css' && asset_type != 'js' {
|
if asset_type != 'css' && asset_type != 'js' {
|
||||||
panic('$unknown_asset_type_error ($asset_type).')
|
panic('$unknown_asset_type_error ($asset_type).')
|
||||||
}
|
}
|
||||||
assets := if asset_type == 'css' {
|
assets := if asset_type == 'css' { am.css } else { am.js }
|
||||||
am.css
|
|
||||||
} else {
|
|
||||||
am.js
|
|
||||||
}
|
|
||||||
return assets
|
return assets
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue