From 36cfafcbf9c09ab93b3382379e748e55e9b91d5f Mon Sep 17 00:00:00 2001 From: Steven Hugg Date: Sun, 23 Aug 2020 13:40:04 -0500 Subject: [PATCH] restartAtPC(), debug info --- css/ui.css | 2 + package-lock.json | 2 +- package.json | 2 +- presets/basic/hello.bas | 104 +++-------------------------------- presets/basic/tutorial.bas | 99 +++++++++++++++++++++++++++++++++ src/common/baseplatform.ts | 1 + src/common/basic/compiler.ts | 4 +- src/common/teletype.ts | 3 + src/ide/ui.ts | 16 +++++- src/platform/basic.ts | 21 +++++-- 10 files changed, 146 insertions(+), 108 deletions(-) create mode 100644 presets/basic/tutorial.bas diff --git a/css/ui.css b/css/ui.css index fa0956b8..eea55a27 100644 --- a/css/ui.css +++ b/css/ui.css @@ -129,6 +129,8 @@ div.mem_info { font-family: "Andale Mono", "Menlo", "Lucida Console", monospace; font-size: 12pt; box-shadow: 0px 0px 8px rgba(0,0,0,.5); + max-height: 90vh; + overflow-y: auto; } div.mem_info a { color: #99ff99; diff --git a/package-lock.json b/package-lock.json index 09244cbd..3d05a552 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "8bitworkshop", - "version": "3.6.1", + "version": "3.7.0", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 8ee4b593..773ec63a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "8bitworkshop", - "version": "3.6.1", + "version": "3.7.0", "author": "Steven Hugg", "description": "8bitworkshop.com", "repository": { diff --git a/presets/basic/hello.bas b/presets/basic/hello.bas index 8713489f..dd66bb2f 100644 --- a/presets/basic/hello.bas +++ b/presets/basic/hello.bas @@ -1,99 +1,9 @@ OPTION DIALECT DARTMOUTH -001 REM THIS IS A PROGRAM WRITTEN IN BASIC. -002 REM YOU CAN WRITE ONE STATEMENT PER LINE. -003 REM EACH STATEMENT MUST HAVE A LINE NUMBER. -004 REM THE "REM" LINES ARE COMMENTS, WHICH ARE IGNORED -005 ' YOU CAN ALSO DO COMMENTS WITH APOSTROPHES -006 ' LET'S START WITH A "PRINT"... -100 PRINT "HELLO! LET'S PROGRAM IN BASIC." -101 PRINT ' <-- THIS PRINTS A BLANK LINE, IT LOOKS NICER -105 ' "INPUT" WAITS FOR USER INPUT FROM THE KEYBOARD -106 ' THE NUMBER ENTERED WILL GO INTO THE VARIABLE "N" -110 INPUT "FIRST, TELL ME YOUR FAVORITE NUMBER";N -111 PRINT -115 ' YOU CAN DO CALCULATIONS WITH THE + - / * OPERATORS -116 ' THE ^ IS AN EXPONENT, SO N^2 IS N-SQUARED -119 ' "LET" ASSIGNS THE RESULT TO A VARIABLE -120 LET Z = N^2 -121 ' THE SEMICOLON ";" SEPARATES THINGS TO BE PRINTED -122 PRINT "THAT'S A GOOD ONE! I LIKE";Z;"MYSELF." -123 PRINT -125 ' IF A VARIABLE ENDS IN "$" IT IS A STRING -126 ' AND CONTAINS CHARACTERS INSTEAD OF A NUMBER -127 ' LET'S READ FROM THE KEYBOARD INTO THE A$ VARIABLE -130 INPUT "WOULD YOU MIND TYPING IN YOUR NAME";A$ -131 PRINT -135 ' WE CAN PRINT MULTIPLE THINGS PER LINE -136 ' IN THIS BASIC DIALECT, NUMBERS ARE PRINTED -137 ' WITH SPACES BEFORE AND AFTER -140 PRINT "GOOD TO MEET YOU, ";A$;" WHO LOVES";N;"!" -141 PRINT -150 INPUT "WOULD YOU LIKE TO SEE ME CALCULATE";B$ -151 PRINT -155 ' "IF" CAN TEST A CONDITION -156 ' AND JUMP TO A DIFFERENT LINE IF IT IS TRUE -160 IF B$ = "Y" THEN 180 -161 IF B$ = "YES" THEN 180 -170 PRINT "TOO BAD, ";A$;"! WE'RE DOING THIS." -180 PRINT -190 PRINT "WATCH ME COUNT..." -195 ' THIS "FOR" STATEMENT STARTS A LOOP WHICH SETS -196 ' VARIABLE I TO 1 AND COUNTS TO 50 -200 FOR I = 1 TO 50 -210 PRINT I, ' USE A COMMA FOR NEAT PRINT ZONES -220 NEXT I ' REPEAT LOOP -225 ' USING THE COMMA (OR SEMICOLON) IN THE PRINT STATEMENT -226 ' KEEPS THE CURSOR ON THE SAME LINE, SO WE PRINT -227 ' A BLANK LINE TO RETURN TO THE LEFT MARGIN -230 PRINT -240 PRINT "I CAN ALSO GRAPH TRIG FUNCTIONS!" -245 ' YOU CAN DEFINE YOUR OWN FUNCTIONS WITH "DEF" -246 ' FUNCTIONS MUST START WITH "FN" -250 DEF FNY(X) = (SIN(X*0.3)+1)*30+2 -260 FOR I = 1 TO 25 -270 PRINT TAB(FNY(I));"*" -280 NEXT I -300 ' YOU CAN DEFINE AN ARRAY WITH "DIM" -301 ' YOU CAN HAVE ARRAYS OF EITHER NUMBERS OR STRINGS -310 DIM T$(15),A$(15),W(15) -315 ' "READ" LOADS FROM "DATA" STATEMENTS -316 ' DATA CAN BE ANYWHERE, OURS IS AT LINE 900 -320 FOR I = 1 TO 15 -330 READ T$(I),A$(I),W(I) -340 NEXT I -350 ' NOW THE ARRAYS ARE FILLED WITH DATA -351 ' SO LET'S PICK A VALUE AT RANDOM -352 ' THE RND FUNCTION RETURNS A RANDOM NUMBER -353 ' FIRST WE USE "RANDOMIZE" TO INITIALIZE THE -354 ' RANDOM NUMBER GENERATOR -360 RANDOMIZE -362 ' "LET" ASSIGNS A VARIABLE FROM AN EXPRESSION -370 LET J = INT(15*RND) -380 PRINT "MY FAVORITE SONG IS '";T$(J);"'" -390 PRINT "BY ";A$(J);", DO YOU KNOW IT?" -400 PRINT "IT SPENT";W(J);"WEEKS ATOP THE CHARTS." -410 PRINT -890 ' HERE'S THE DATA WE READ EARLIER -891 ' WE CAN USE NUMBERS, QUOTED OR UNQUOTED STRINGS -900 DATA "HELLO, GOODBYE",THE BEATLES,2 -901 DATA "JUDY IN DISGUISE",JOHN FRED AND HIS PLAYBOY BAND,2 -902 DATA "GREEN TAMBOURINE",THE LEMON PIPERS,1 -903 DATA "LOVE IS BLUE",PAUL MAURIAT,5 -904 DATA "(SITTIN' ON) THE DOCK OF THE BAY",OTIS REDDING,4 -905 DATA "HONEY",BOBBY GOLDSBORO,5 -906 DATA "TIGHTEN UP",ARCHIE BELL & THE DRELLS,3 -907 DATA "MRS. ROBINSON",SIMON & GARFUNKEL,3 -908 DATA "THIS GUY'S IN LOVE WITH YOU",HERB ALPERT,4 -909 DATA "GRAZING IN THE GRASS",HUGH MASEKELA,2 -910 DATA "HELLO, I LOVE YOU",THE DOORS,2 -911 DATA "PEOPLE GOT TO BE FREE",THE RASCALS,5 -912 DATA "HARPER VALLEY PTA",JEANNIE C. RILEY,1 -913 DATA "HEY JUDE",THE BEATLES,9 -914 DATA "LOVE CHILD",DIANA ROSS & THE SUPREMES,2 -915 DATA "I HEARD IT THROUGH THE GRAPEVINE",MARVIN GAYE,3 -979 ' WE'RE DONE, SAY GOODBYE TO THE USER -980 PRINT "I APOLOGIZE, BUT I AM FATIGUED FROM ALL OF THIS" -981 PRINT "CALCULATING. I SHALL TAKE MY LEAVE OF YOU NOW." -990 PRINT "NICE MEETING YOU, ";A$;"." -998 ' PROGRAMS MUST END WITH "END" IN THIS DIALECT +10 PRINT "HELLO! LET'S PROGRAM IN BASIC." +20 INPUT "WOULD YOU MIND TYPING IN YOUR NAME";A$ +30 PRINT "THANKS, ";A$;"! THIS WILL BE FUN!" +40 INPUT "NOW TELL ME YOUR FAVORITE NUMBER";N +50 LET B=N^2 +60 PRINT "THAT'S A GOOD ONE! I LIKE";B;"MYSELF." +70 PRINT "NICE MEETING YOU, ";A$;"." 999 END diff --git a/presets/basic/tutorial.bas b/presets/basic/tutorial.bas new file mode 100644 index 00000000..8713489f --- /dev/null +++ b/presets/basic/tutorial.bas @@ -0,0 +1,99 @@ +OPTION DIALECT DARTMOUTH +001 REM THIS IS A PROGRAM WRITTEN IN BASIC. +002 REM YOU CAN WRITE ONE STATEMENT PER LINE. +003 REM EACH STATEMENT MUST HAVE A LINE NUMBER. +004 REM THE "REM" LINES ARE COMMENTS, WHICH ARE IGNORED +005 ' YOU CAN ALSO DO COMMENTS WITH APOSTROPHES +006 ' LET'S START WITH A "PRINT"... +100 PRINT "HELLO! LET'S PROGRAM IN BASIC." +101 PRINT ' <-- THIS PRINTS A BLANK LINE, IT LOOKS NICER +105 ' "INPUT" WAITS FOR USER INPUT FROM THE KEYBOARD +106 ' THE NUMBER ENTERED WILL GO INTO THE VARIABLE "N" +110 INPUT "FIRST, TELL ME YOUR FAVORITE NUMBER";N +111 PRINT +115 ' YOU CAN DO CALCULATIONS WITH THE + - / * OPERATORS +116 ' THE ^ IS AN EXPONENT, SO N^2 IS N-SQUARED +119 ' "LET" ASSIGNS THE RESULT TO A VARIABLE +120 LET Z = N^2 +121 ' THE SEMICOLON ";" SEPARATES THINGS TO BE PRINTED +122 PRINT "THAT'S A GOOD ONE! I LIKE";Z;"MYSELF." +123 PRINT +125 ' IF A VARIABLE ENDS IN "$" IT IS A STRING +126 ' AND CONTAINS CHARACTERS INSTEAD OF A NUMBER +127 ' LET'S READ FROM THE KEYBOARD INTO THE A$ VARIABLE +130 INPUT "WOULD YOU MIND TYPING IN YOUR NAME";A$ +131 PRINT +135 ' WE CAN PRINT MULTIPLE THINGS PER LINE +136 ' IN THIS BASIC DIALECT, NUMBERS ARE PRINTED +137 ' WITH SPACES BEFORE AND AFTER +140 PRINT "GOOD TO MEET YOU, ";A$;" WHO LOVES";N;"!" +141 PRINT +150 INPUT "WOULD YOU LIKE TO SEE ME CALCULATE";B$ +151 PRINT +155 ' "IF" CAN TEST A CONDITION +156 ' AND JUMP TO A DIFFERENT LINE IF IT IS TRUE +160 IF B$ = "Y" THEN 180 +161 IF B$ = "YES" THEN 180 +170 PRINT "TOO BAD, ";A$;"! WE'RE DOING THIS." +180 PRINT +190 PRINT "WATCH ME COUNT..." +195 ' THIS "FOR" STATEMENT STARTS A LOOP WHICH SETS +196 ' VARIABLE I TO 1 AND COUNTS TO 50 +200 FOR I = 1 TO 50 +210 PRINT I, ' USE A COMMA FOR NEAT PRINT ZONES +220 NEXT I ' REPEAT LOOP +225 ' USING THE COMMA (OR SEMICOLON) IN THE PRINT STATEMENT +226 ' KEEPS THE CURSOR ON THE SAME LINE, SO WE PRINT +227 ' A BLANK LINE TO RETURN TO THE LEFT MARGIN +230 PRINT +240 PRINT "I CAN ALSO GRAPH TRIG FUNCTIONS!" +245 ' YOU CAN DEFINE YOUR OWN FUNCTIONS WITH "DEF" +246 ' FUNCTIONS MUST START WITH "FN" +250 DEF FNY(X) = (SIN(X*0.3)+1)*30+2 +260 FOR I = 1 TO 25 +270 PRINT TAB(FNY(I));"*" +280 NEXT I +300 ' YOU CAN DEFINE AN ARRAY WITH "DIM" +301 ' YOU CAN HAVE ARRAYS OF EITHER NUMBERS OR STRINGS +310 DIM T$(15),A$(15),W(15) +315 ' "READ" LOADS FROM "DATA" STATEMENTS +316 ' DATA CAN BE ANYWHERE, OURS IS AT LINE 900 +320 FOR I = 1 TO 15 +330 READ T$(I),A$(I),W(I) +340 NEXT I +350 ' NOW THE ARRAYS ARE FILLED WITH DATA +351 ' SO LET'S PICK A VALUE AT RANDOM +352 ' THE RND FUNCTION RETURNS A RANDOM NUMBER +353 ' FIRST WE USE "RANDOMIZE" TO INITIALIZE THE +354 ' RANDOM NUMBER GENERATOR +360 RANDOMIZE +362 ' "LET" ASSIGNS A VARIABLE FROM AN EXPRESSION +370 LET J = INT(15*RND) +380 PRINT "MY FAVORITE SONG IS '";T$(J);"'" +390 PRINT "BY ";A$(J);", DO YOU KNOW IT?" +400 PRINT "IT SPENT";W(J);"WEEKS ATOP THE CHARTS." +410 PRINT +890 ' HERE'S THE DATA WE READ EARLIER +891 ' WE CAN USE NUMBERS, QUOTED OR UNQUOTED STRINGS +900 DATA "HELLO, GOODBYE",THE BEATLES,2 +901 DATA "JUDY IN DISGUISE",JOHN FRED AND HIS PLAYBOY BAND,2 +902 DATA "GREEN TAMBOURINE",THE LEMON PIPERS,1 +903 DATA "LOVE IS BLUE",PAUL MAURIAT,5 +904 DATA "(SITTIN' ON) THE DOCK OF THE BAY",OTIS REDDING,4 +905 DATA "HONEY",BOBBY GOLDSBORO,5 +906 DATA "TIGHTEN UP",ARCHIE BELL & THE DRELLS,3 +907 DATA "MRS. ROBINSON",SIMON & GARFUNKEL,3 +908 DATA "THIS GUY'S IN LOVE WITH YOU",HERB ALPERT,4 +909 DATA "GRAZING IN THE GRASS",HUGH MASEKELA,2 +910 DATA "HELLO, I LOVE YOU",THE DOORS,2 +911 DATA "PEOPLE GOT TO BE FREE",THE RASCALS,5 +912 DATA "HARPER VALLEY PTA",JEANNIE C. RILEY,1 +913 DATA "HEY JUDE",THE BEATLES,9 +914 DATA "LOVE CHILD",DIANA ROSS & THE SUPREMES,2 +915 DATA "I HEARD IT THROUGH THE GRAPEVINE",MARVIN GAYE,3 +979 ' WE'RE DONE, SAY GOODBYE TO THE USER +980 PRINT "I APOLOGIZE, BUT I AM FATIGUED FROM ALL OF THIS" +981 PRINT "CALCULATING. I SHALL TAKE MY LEAVE OF YOU NOW." +990 PRINT "NICE MEETING YOU, ";A$;"." +998 ' PROGRAMS MUST END WITH "END" IN THIS DIALECT +999 END diff --git a/src/common/baseplatform.ts b/src/common/baseplatform.ts index 630d3f96..d037793f 100644 --- a/src/common/baseplatform.ts +++ b/src/common/baseplatform.ts @@ -105,6 +105,7 @@ export interface Platform { runEval?(evalfunc : DebugEvalCondition) : void; runToFrameClock?(clock : number) : void; stepOver?() : void; + restartAtPC?(pc:number) : boolean; getOpcodeMetadata?(opcode:number, offset:number) : OpcodeMetadata; //TODO getSP?() : number; diff --git a/src/common/basic/compiler.ts b/src/common/basic/compiler.ts index 983654ce..8e7e898f 100644 --- a/src/common/basic/compiler.ts +++ b/src/common/basic/compiler.ts @@ -1,6 +1,4 @@ import { WorkerError, CodeListingMap, SourceLocation, SourceLine } from "../workertypes"; -import { BasicMachineState } from "../devices"; -import { merge } from "jquery"; export interface BASICOptions { dialectName : string; // use this to select the dialect @@ -1907,7 +1905,7 @@ const BUILTIN_DEFS : BuiltinFunctionDef[] = [ ['PI', [], 'number'], ['POS', ['number'], 'number' ], // arg ignored ['POS', ['string','string'], 'number' ], // HP POS - ['LEFT$', ['string', 'number'], 'string' ], + ['RIGHT$', ['string', 'number'], 'string' ], ['RND', [], 'number' ], ['RND', ['number'], 'number' ], ['ROUND', ['number'], 'number' ], diff --git a/src/common/teletype.ts b/src/common/teletype.ts index 6e741a54..b3ebc53f 100644 --- a/src/common/teletype.ts +++ b/src/common/teletype.ts @@ -230,6 +230,9 @@ export class TeleTypeWithKeyboard extends TeleType { this.input.value = ''; this.waitingfor = null; } + cancelinput() { + this.sendinput(''); + } sendkey(e: KeyboardEvent) { if (this.waitingfor == 'line') { if (e.key == "Enter") { diff --git a/src/ide/ui.ts b/src/ide/ui.ts index 18ba51e5..5c32d2c7 100644 --- a/src/ide/ui.ts +++ b/src/ide/ui.ts @@ -188,7 +188,7 @@ function initProject() { toolbar.removeClass("is-busy"); toolbar.removeClass("has-errors"); // may be added in next callback projectWindows.setErrors(null); - $("#error_alert").hide(); + hideErrorAlerts(); } $('#compile_spinner').css('visibility', busy ? 'visible' : 'hidden'); }; @@ -1090,6 +1090,10 @@ function getErrorElement(err : WorkerError) { return span; } +function hideErrorAlerts() { + $("#error_alert").hide(); +} + function showErrorAlert(errors : WorkerError[]) { var div = $("#error_alert_msg").empty(); for (var err of errors.slice(0,10)) { @@ -1291,6 +1295,7 @@ function _resume() { console.log("Resumed"); } setDebugButtonState("go", "active"); + // TODO: hide alerts, but only if exception generated them } function resume() { @@ -1346,6 +1351,12 @@ export function runToPC(pc: number) { } } +function restartAtCursor() { + if (platform.restartAtPC(getEditorPC())) { + resume(); + } else alertError(`Could not restart program at selected line.`); +} + function runToCursor() { runToPC(getEditorPC()); } @@ -1645,6 +1656,9 @@ function setupDebugControls() { uitoolbar.add('ctrl+alt+r', 'Reset', 'glyphicon-refresh', resetAndRun).prop('id','dbg_reset'); uitoolbar.add('ctrl+alt+,', 'Pause', 'glyphicon-pause', pause).prop('id','dbg_pause'); uitoolbar.add('ctrl+alt+.', 'Resume', 'glyphicon-play', resume).prop('id','dbg_go'); + if (platform.restartAtPC) { + uitoolbar.add('ctrl+alt+/', 'Restart at Cursor', 'glyphicon-play-circle', restartAtCursor).prop('id','dbg_restartatline'); + } uitoolbar.newGroup(); uitoolbar.grp.prop('id','debug_bar'); if (platform.runEval) { diff --git a/src/platform/basic.ts b/src/platform/basic.ts index da2ca2a6..2addf650 100644 --- a/src/platform/basic.ts +++ b/src/platform/basic.ts @@ -9,7 +9,8 @@ import { TeleTypeWithKeyboard } from "../common/teletype"; import { lpad } from "../common/util"; const BASIC_PRESETS = [ - { id: 'hello.bas', name: 'Tutorial' }, + { id: 'hello.bas', name: 'Hello' }, + { id: 'tutorial.bas', name: 'Tutorial' }, { id: 'sieve.bas', name: 'Sieve Benchmark' }, { id: 'mortgage.bas', name: 'Interest Calculator' }, { id: '23match.bas', name: '23 Matches' }, @@ -204,9 +205,9 @@ class BASICPlatform implements Platform { if (o != null) return `${sym} = ${o}`; } showHelp(tool:string, ident:string) { - window.open("https://8bitworkshop.com/blog/platforms/basic/", "_help"); + window.open("https://8bitworkshop.com/blog/platforms/basic/#basicreference", "_help"); } - /* + getDebugCategories() { return ['Variables']; } @@ -221,13 +222,12 @@ class BASICPlatform implements Platform { vars.sort(); for (var name of vars) { var value = this.runtime.vars[name]; - var valstr = value.toString(); + var valstr = JSON.stringify(value); if (valstr.length > 24) valstr = `${valstr.substr(0,24)}...(${valstr.length})`; s += lpad(name,3) + " = " + valstr + "\n"; } return s; } - */ // TODO: debugging (get running state, etc) @@ -279,6 +279,17 @@ class BASICPlatform implements Platform { this.debugTrap = () => evalfunc(this.getCPUState()); this.resume(); } + restartAtPC?(pc:number) : boolean { + pc = Math.round(pc); + if (pc >= 0 && pc < this.runtime.allstmts.length) { + this.runtime.curpc = pc; + this.tty.cancelinput(); + this.clock = 0; + return true; + } else { + return false; + } + } } //