Skip to content
Snippets Groups Projects
Commit 2c51c2c2 authored by Deucе's avatar Deucе :ok_hand_tone4:
Browse files

More core REF fixes...

1) Comments do not start with a ;
   Any line that doesn't start with an @ is either a parameter to
   the last command (such as in @show), or is ignored.  Further,
   "extra" arguments are also ignored.  This means you can literally
   type comments almost anywhere.
2) There is a maximum "call stack" of two "frames".  If you nest
   subroutines three deep, the first one will never be returned to.
3) Implement @routineabort.
4) If @run is used in a subroutine, it acts as an immediate return
   The arguments are not consulted, and no error is displayed.
5) Of course, if you call subroutines three deep and return from
   two of them, the first subroutine is now the topmost frame, so
   run behaves normally there.
parent c387a7dd
No related branches found
No related tags found
1 merge request!463MRC mods by Codefenix (2024-10-20)
...@@ -228,6 +228,13 @@ function yes_no(y, title, question) { ...@@ -228,6 +228,13 @@ function yes_no(y, title, question) {
} }
function run_ref(sec, fname) function run_ref(sec, fname)
{
calldepth = 0;
insane_run_ref(sec, fname);
}
var calldepth = 0;
function insane_run_ref(sec, fname)
{ {
var line; var line;
var m; var m;
...@@ -236,6 +243,11 @@ function run_ref(sec, fname) ...@@ -236,6 +243,11 @@ function run_ref(sec, fname)
var ret; var ret;
var refret; var refret;
if (++calldepth > 2)
calldepth = 2;
if (calldepth < 1)
return;
fname = fname.toLowerCase(); fname = fname.toLowerCase();
sec = sec.toLowerCase(); sec = sec.toLowerCase();
...@@ -244,7 +256,8 @@ function run_ref(sec, fname) ...@@ -244,7 +256,8 @@ function run_ref(sec, fname)
var ret = []; var ret = [];
while (line < files[fname].lines.length && files[fname].lines[line+1].search(/^\s*@/) === -1) { while (line < files[fname].lines.length && files[fname].lines[line+1].search(/^\s*@/) === -1) {
if (files[fname].lines[line+1].search(/^\s*;/) === -1) // NOTE: "Comments" are not special in any way (see top of loop in main body of insane_run_ref()
//if (files[fname].lines[line+1].search(/^\s*;/) === -1)
ret.push(files[fname].lines[line+1]); ret.push(files[fname].lines[line+1]);
line++; line++;
} }
...@@ -283,9 +296,9 @@ function run_ref(sec, fname) ...@@ -283,9 +296,9 @@ function run_ref(sec, fname)
}, },
'getkey':function(args) { 'getkey':function(args) {
if (!dk.console.waitkey(0)) if (!dk.console.waitkey(0))
return '_'; setvar(args[0], '_');
lastkey = now(); lastkey = now();
return dk.console.getkey(); setvar(args[0], dk.console.getkey());
}, },
'goto':function(args) { 'goto':function(args) {
// NOTE: This doesn't use getvar() because GREEN.REF has 'do goto bank' // NOTE: This doesn't use getvar() because GREEN.REF has 'do goto bank'
...@@ -561,6 +574,7 @@ function run_ref(sec, fname) ...@@ -561,6 +574,7 @@ function run_ref(sec, fname)
if (tmp.Record >= 200) { if (tmp.Record >= 200) {
pfile.file.position = pfile.RecordLength * 200; pfile.file.position = pfile.RecordLength * 200;
pfile.truncate(pfile.RecordLength * 200); pfile.truncate(pfile.RecordLength * 200);
// TODO: What is the stack depth here?
run_ref('full','gametxt.ref'); run_ref('full','gametxt.ref');
exit(0); exit(0);
} }
...@@ -1277,7 +1291,8 @@ function run_ref(sec, fname) ...@@ -1277,7 +1291,8 @@ function run_ref(sec, fname)
rp.forEach(function(pl, i) { rp.forEach(function(pl, i) {
player = pl; player = pl;
run_ref(format('`p%02d', getvar(args[2])), fname); // TODO: It is assumed this takes a stack frame.
insane_run_ref(format('`p%02d', getvar(args[2])), fname);
}); });
player = op; player = op;
}, },
...@@ -1306,25 +1321,26 @@ function run_ref(sec, fname) ...@@ -1306,25 +1321,26 @@ function run_ref(sec, fname)
}, },
'routine':function(args) { 'routine':function(args) {
var s = replace_vars(args[0]).toLowerCase(); var s = replace_vars(args[0]).toLowerCase();
if (args.length === 1) { var fn = fname;
run_ref(s, fname); var ret;
return;
} if (args.length > 1 && args[1].toLowerCase() === 'in') {
if (args[1].toLowerCase() === 'in') { fn = replace_vars(args[2]);
run_ref(s, args[2]);
return; return;
} }
throw new Error('Unable to parse routine "'+s+'" at '+fname+':'+line); if (insane_run_ref(s, fn, true) === 'ROUTINEABORT')
return 'ROUTINEABORT';
}, },
'routineabort':function(args) { 'routineabort':function(args) {
// TODO: Implement this. // TODO: Implemented in line parser
throw new Error('RoutineAbort is not implemented');
}, },
'run':function(args) { 'run':function(args) {
// TODO: Test if the ref that's ran actually returns here, or if it simple aborts execution! // TODO: Test if the ref that's ran actually returns here, or if it simple aborts execution!
var f = fname; var f = fname;
var s = replace_vars(args[0]).toLowerCase(); var s = replace_vars(args[0]).toLowerCase();
if (calldepth > 1)
return false;
if (args.length > 2 && args[1].toLowerCase() === 'in') { if (args.length > 2 && args[1].toLowerCase() === 'in') {
f = getvar(args[2]).toLowerCase(); f = getvar(args[2]).toLowerCase();
} }
...@@ -1334,10 +1350,17 @@ function run_ref(sec, fname) ...@@ -1334,10 +1350,17 @@ function run_ref(sec, fname)
load_ref(f); load_ref(f);
if (files[f] === undefined) if (files[f] === undefined)
throw new Error('Unable to load REF "'+f+'"'); throw new Error('Unable to load REF "'+f+'"');
if (files[f].section[s] === undefined) if (files[f].section[s] === undefined) {
throw new Error('Unable to find run section '+s+' in '+f+' at '+fname+':'+line); sln('');
lln('ERROR = '+s+' not found in '+fname+'!');
// Throwing this error breaks NPCs in baraks.
// But you still end up with no map and looking bad.
//throw new Error('Unable to find run section '+s+' in '+f+' at '+fname+':'+line);
}
else {
fname = f; fname = f;
line = files[f].section[s].line; line = files[f].section[s].line;
}
}, },
'savecursor':function(args) { 'savecursor':function(args) {
saved_cursor = {x:scr.pos.x, y:scr.pos.y}; saved_cursor = {x:scr.pos.x, y:scr.pos.y};
...@@ -1661,18 +1684,28 @@ rescan: ...@@ -1661,18 +1684,28 @@ rescan:
line = files[fname].section[sec].line; line = files[fname].section[sec].line;
while (1) { while (1) {
/*
* Actually ANY LINE where the first non-whitespace is not
* an '@' is either ignored or used by the previous command.
* That means we can just toss out overthing before parsing the next command.
*/
getlines();
line++; line++;
if (line >= files[fname].lines.length) if (line >= files[fname].lines.length)
return refret; break;
cl = files[fname].lines[line].replace(/^\s*/,''); cl = files[fname].lines[line].replace(/^\s*/,'');
if (cl.search(/^@#/) !== -1) if (cl.search(/^@#/) !== -1)
return refret; break;
if (cl.search(/^\s*@closescript/i) !== -1) if (cl.search(/^\s*@closescript/i) !== -1)
return refret; break;
if (cl.search(/^\s*@itemexit/i) !== -1) { if (cl.search(/^\s*@itemexit/i) !== -1) {
refret = 'ITEMEXIT'; refret = 'ITEMEXIT';
continue; continue;
} }
if (cl.search(/^\s*@routineabort/i) !== -1) {
refret = 'ROUTINEABORT';
continue;
}
if (cl.search(/^;/) !== -1) if (cl.search(/^;/) !== -1)
continue; continue;
if (cl.search(/^@/) === -1) { if (cl.search(/^@/) === -1) {
...@@ -1688,7 +1721,19 @@ rescan: ...@@ -1688,7 +1721,19 @@ rescan:
while (args !== undefined && args.length > 1 && args[args.length - 1] === '') while (args !== undefined && args.length > 1 && args[args.length - 1] === '')
args.pop(); args.pop();
ret = handle(args); ret = handle(args);
// Returns false to abort.
if (calldepth < 1)
ret = 'ROUTINEABORT';
if (ret === 'ROUTINEABORT') {
refret = ret;
ret = false;
} }
if (ret === false)
break;
}
if (--calldepth < 1)
refret == 'ROUTINEABORT';
return refret;
} }
function load_player() function load_player()
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment