Shop OBEX P1 Docs P2 Docs Learn Events
Why C is better than BASIC, can anyone provide live example? - Page 8 — Parallax Forums

Why C is better than BASIC, can anyone provide live example?

168101112

Comments

  • idbruceidbruce Posts: 6,197
    edited 2015-04-03 08:45
    Mickster
    We have one who makes claims that C will "blow the pants off Basic" but can't tell us how/why. I guess he just read it somewhere.

    Tell us all about Provisional Patents Mick :)
  • David BetzDavid Betz Posts: 14,516
    edited 2015-04-03 08:45
    Mickster wrote: »
    @CuriousOne

    "can anyone provide live example?".....11 pages in and apparently not!

    VB and VC are "off topic" but apparently Scheme/Lisp/Pascal are on topic (I must be misinterpreting the title again)

    We have one who makes claims that C will "blow the pants off Basic" but can't tell us how/why. I guess he just read it somewhere.

    The statement was made: "Also, what your program does not use does not get linked in, that's great when you want tiny code." So I provided a compiled Windows BASIC "Hello World" that is ~8KB (no dependencies) and it fell on deaf ears.

    A data structure example written in C was used as an example of something that couldn't be done in BASIC. It took like 15mins (I'm slow on the keyboard) to replicate it using a 28 year old DOS BASIC and the bonus was improved readability.
    The question was too vague to be answered so people have been going off on tangents.
  • Heater.Heater. Posts: 21,230
    edited 2015-04-03 08:50
    Mickster,
    "can anyone provide live example?".....11 pages in and apparently not!
    It helps to read the pages if you are going to talk about them:

    FFT in C post #14

    FFT in BASIC via #78

    How live do you want?


    Yes, VB and VC are almost certainly off topic. The subject is languages not IDEs. How are you going to run any of the code they generate on Parallax product, or anywhere but on Windows, anyway?

    Yes, Scheme/Lisp/Pascal are also off topic, but what the heck, we have flogged the BASIC/C debate to death. It's boring anyway.
    So I provided a compiled Windows BASIC "Hello World" that is ~8KB (no dependencies) and it fell on deaf ears.
    I noticed that. I don't understand what you mean by it. 8K is huge. OK point taken, a BASIC compiler can also only pull in code that it needs for the program. But heck the young Bill Gates and co. could fit an entire BASIC interpreter in 8K, even 4K.
  • potatoheadpotatohead Posts: 10,261
    edited 2015-04-03 08:56
    Pffft! That's nothing.

    Here is some small for you: http://www.muppetlabs.com/~breadbox/software/tiny/teensy.html

    Once that is under your belt, polish it up with some system calls, and you can put an entire app in 4K.

    :)
  • MicksterMickster Posts: 2,693
    edited 2015-04-03 08:58
    Dave Hein wrote: »
    Mickster, your link goes to a hello.exe file on dropbox. I'm not sure how useful that is for proving your point. A C version of "Hello World" is "void main() { printf("Hello World\n"); }". It compiles to a 4,296 byte CMM binary.
    '-------------------------------------------------------------------------------
    '
    '  HELLO.BAS example for PowerBASIC for Windows
    '  Copyright (c) 1997-2005 PowerBASIC, Inc.
    '  All Rights Reserved.
    '
    '-------------------------------------------------------------------------------
    
    #COMPILER PBWIN 9
    #COMPILE EXE
    
    ' The resource file gives the EXE program the "hello" icon in Explorer,
    ' and provides it with Windows version information.
    #RESOURCE "Hello.pbr"
    
    FUNCTION PBMAIN () AS LONG
    
        MSGBOX "Hello, World!"
    
    END FUNCTION
    
    
    

    Dave Hein wrote: »
    I have a threaded chess program written in C at http://forums.parallax.com/showthread.php/148414-Threaded-Chess . I'm looking forward to seeing your BASIC version of it. :)

    Are you asserting here BASIC doesn't do threads or is there some other *magic* in the C language that I need to know about?

    PowerBASIC is entirely thread-safe, so multi-threaded applications are a breeze. Isn't it good to know your program can handle 2, 3, or 5000 tasks, all at the same time? You can print a report, while still allowing data entry. Watch for a hardware signal, while calculating data services. All the power you need is packed right into the PowerBASIC Thread Statement, along with its simple extensions. There is even a built-in THREAD object that offers a collection of methods which allow you to easily create and maintain additional threads of execution in your programs. Functions, Subroutines, Methods, and Properties can even be marked as THREADSAFE. When a procedure is declared THREADSAFE, PowerBASIC automatically establishes a semaphore which allows only one thread to execute it at a time. Others must wait until the first thread exits the THREADSAFE procedure before they are allowed to begin. This is important to protect global data (global, threaded, static, and instance variables) from corruption by interaction of the threads. PowerBASIC even offers THREADED variables for "Thread Local Storage" -- each THREAD get its own unique copy of the variable -- automatically.
  • idbruceidbruce Posts: 6,197
    edited 2015-04-03 08:58
    Heater
    Yes, VB and VC are almost certainly off topic. The subject is languages not IDEs.

    Please tell me how LISP, PASCAL, and any other language that you have discussed, besides BASIC and C is on topic.

    EDIT: At least VB and VC apply to C and BASIC
  • Dave HeinDave Hein Posts: 6,347
    edited 2015-04-03 09:01
    Mickster wrote: »
    Are you asserting here BASIC doesn't do threads or is there some other *magic* in the C language that I need to know about?
    I'm not asserting anything. I just want to see the BASIC version of the program. You don't even need to do the threaded part if you don't want to. A single-threaded BASIC version would be fine.
  • mindrobotsmindrobots Posts: 6,506
    edited 2015-04-03 09:07
    potatohead wrote: »
    Pffft! That's nothing.

    Here is some small for you: http://www.muppetlabs.com/~breadbox/software/tiny/teensy.html

    Once that is under your belt, polish it up with some system calls, and you can put an entire app in 4K.

    :)

    Ahhhh, those were the days!!
    On the other hand, every single byte in this executable file can be accounted for and justified. How many executables have you created lately that you can say that about?

    I miss lovingly hand crafting programs so they fit in tiny spaces!
  • Heater.Heater. Posts: 21,230
    edited 2015-04-03 09:09
    idbruce,
    Please tell me how LISP, PASCAL, and any other language that you have discussed, besides BASIC and C is on topic.
    Why would I? I agree with you. See my post #215 above: "Yes, Scheme/Lisp/Pascal are also off topic..."
  • mindrobotsmindrobots Posts: 6,506
    edited 2015-04-03 09:12
    idbruce wrote: »
    Heater



    Please tell me how LISP, PASCAL, and any other language that you have discussed, besides BASIC and C is on topic.

    EDIT: At least VB and VC apply to C and BASIC

    When faced with an unanswerable question, "Why C is better than BASIC , can anyone provide examples?", once one gets bored, why not wander off through the garden and see what other tea trolleys one can topple??

    I think some of the off topic discussions have been rather enlightening and thought provoking!
  • idbruceidbruce Posts: 6,197
    edited 2015-04-03 09:18
    Rick
    I think some of the off topic discussions have been rather enlightening and thought provoking!

    I agree. I just don't think it was appropriate for Heater to single me out, when he is all over the place himself.
  • MicksterMickster Posts: 2,693
    edited 2015-04-03 09:19
    mindrobots wrote: »
    I think some of the off topic discussions have been rather enlightening and thought provoking!

    Oh absolutely! In fact, this thread inspired me to pull out my old DOS development system and I am now considering FreeDOS + QuickBASIC for an application that just came up....don't know why I didn't think of it before.
  • Heater.Heater. Posts: 21,230
    edited 2015-04-03 09:25
    Mickster,
    I am now considering FreeDOS + QuickBASIC...
    Man, that is scraping the barrel :)
  • PublisonPublison Posts: 12,366
    edited 2015-04-03 09:29
    I really hope the Op is getting the information he requested.

    This always happens when we get in language skirmishes, ( not wars) :)

    Carry on.
  • idbruceidbruce Posts: 6,197
    edited 2015-04-03 09:33
    Way off topic, but since Mickster continually assaults me, I thought I would share the source of our fued. Really kind of comical :)

    Over three years and he still carries a grudge :) LOL

    http://forums.parallax.com/showthread.php/137210-Bragging-Rights!!!-The-Wire-Bending-CNC-and-the-Patent-Application/page2
  • mindrobotsmindrobots Posts: 6,506
    edited 2015-04-03 09:39
    Mickster wrote: »
    Oh absolutely! In fact, this thread inspired me to pull out my old DOS development system and I am now considering FreeDOS + QuickBASIC for an application that just came up....don't know why I didn't think of it before.

    Not to take the OT more OT but.....


    Have you tried a Micromite yet? It's a modernized, controller targeted GWBASIC running on PIC32MX devices. Pretty powerful solution on a $5 chip if you like BASIC.
  • Dave HeinDave Hein Posts: 6,347
    edited 2015-04-03 09:49
    Mickster wrote: »
    Oh absolutely! In fact, this thread inspired me to pull out my old DOS development system and I am now considering FreeDOS + QuickBASIC for an application that just came up....don't know why I didn't think of it before.
    Or if you want to stick with the Prop there are several Basics that have been written for it. You might want to check out the Basic interpreter that runs under spinix. It does a fine job running Star Wars. It is a little slow though. Maybe ebasic would work better. Of course, both of these Basic interpreters were written in C, so if you use either of them you're basically running your Basic program in C. What you really need is a Basic interpreter that was written in Basic. I wonder if one exists.
  • MicksterMickster Posts: 2,693
    edited 2015-04-03 10:13
    Heater. wrote: »
    Mickster,

    Man, that is scraping the barrel :)

    LOL...Cost/time constraints and I was about to no-quote.

    Actually, for all my harping on about QuickBASIC, it turns out to be the glue for a whole bunch of MASM stuff. In fact, I can't tolerate the delays caused by DOS when it decides to stutter for whatever reason so I created a timer interrupt routine to handle the actual machine I/O, This interrupt routine shares data with my QB code so that, when I am running in the QB IDE and decide to suspend/single step through the code, the time critical stuff keeps running, taking care of safety systems, etc. As the I/O status changes, the QB arrays are updated automatically. Being able to make changes in the QB code and continue execution without having to recompile, makes for rapid development and saves scrapping a workpiece (Inconel, stainless steel tubing, etc). My pseudo real-time DOS...LOL
    	Title INT.ASM Interrupt Control Programs
     
    ;Revision History
    	;Rev 001
    	;Rev 002
    	;	Call to PDPress added 1/11/94
    	;Rev 003
    	;	Call to PumpTimer added 6/15/94
    	;Rev 004
    	;	Call to DeadMan added 4/5/95
    	;Rev 005
    	;	Call to IntTimer added 1/6/95
    
    
    
       option segment:use16
    
    	.386
    	.dosseg
    	.model medium,basic
    
    	public  flgoff  
    	public  flgseg  
    	
    	public  inpoff  
    	public  inpseg         
    	
    	public	optoff
    	public	optseg
    	public  outoff  
    	public  outseg  
    	
    	
    	.data
    	
    inpseg  dw      0       ;inputs array 
    inpoff  dw      0
    outseg  dw      0       ;outputs array
    outoff  dw      0
    flgseg  dw      0       ;flags array
    flgoff  dw      0
    optoff	dw	0	;options array
    optseg	dw	0
    
    	.code   
    	
    	extrn	ButtonHandler:proc
    	
    	extrn 	DMCInt:proc
    	extrn	DeadMan:proc
    
    	extrn   inhand:proc
    	extrn	IntTimer:proc
    	
    	extrn	MandStop:proc
    	
    	extrn	PDPress:proc
    
    	extrn   ophand:proc
    	
    	extrn	PumpTimer:proc
    	
    	extrn	ScreenTimer:proc
    	
    
    getw    MACRO   to,from ;get a parameter and save it
    	mov     bx,from
    	mov     ax,[bx]
    	mov     word ptr to,ax
    	ENDM
    	
    	
    install proc    inps:ptr word, ino:ptr word, \
    		ops:ptr word, opo:ptr word, \
    		fls:ptr word, flo:ptr word, \
    		opts:ptr word, opto:ptr word
    
    	
    	pusha                   ;save registers
    	push    ds
    	push    es
    	mov     ax,@data        ;set data seg
    	mov     ds,ax
    		
    	;save passed parameters for interrupt handler use
    		
    	getw    inpseg,inps     ;get inputs segment     
    	getw    inpoff,ino      ;get inputs offset
    	getw    outseg,ops      ;get outputs segment    
    	getw    outoff,opo      ;get outputs offset
    	getw    flgseg,fls      ;get flags segment    
    	getw    flgoff,flo      ;get flags offset
    	getw	optseg,opts	;get options segment
    	getw	optoff,opto	;get options segment
    	
    	mov     ax,3508h        ;get current interrupt vector
    	int     21h
    	mov     word ptr cs:oldvec,bx   ;save segment
    	mov     word ptr cs:oldvec+2,es ;save segment
    	
    	cli                     ;stop interrupt
    		
    	mov     al,36h          ;reprogram timer to 8 times
    	out     43h,al          ;normal speed
    	mov     al,0
    	jmp	@F
    @@:
    	jmp	@F
    @@:
    	out     40h,al
    ;	mov     al,20h
    	MOV		al,4
    	jmp	@F
    @@:
    	jmp	@F
    @@:
    	out     40h,al
    
    	push    cs              ;change interrupt vector
    	pop     ds
    	lea     dx, newint
    	mov     ax,2508h
    	int     21h
    	
    	sti                     ;restart interrupt
    	
    
    	pop     es              ;restore
    	pop     ds
    	popa
    	
    	ret
    install endp
    
    
    uninst  proc
    
    	pusha
    	push 	ds
    	push     es
    	push     si
    	push     di
    	
    	cli                             ;stop interrupts
    		 
    	mov     al,36h                  ;timer back to normal
    	out     43h,al                  ;alert for coming values
    	jmp	@F
    @@:
    	jmp	@F
    @@:
    	mov     al,00h     
    	out     40h,al                  ;lsb
    	jmp	@F
    @@:
    	jmp	@F
    @@:
    	out     40h,al                  ;msb
    	
    	 
    	lds     dx,cs:oldvec            ;restore old interrupt
    	mov     ax,2508h                
    	int     21h                     
    	
    	sti                             ;enable interrupts
    	
    	pop      di
    	pop      si
    	pop      es                      ;restore registers
    	pop      ds
    	popa
    					
    	ret
    uninst  endp
    	 
    newint  proc    near
    	pusha                           ;save registers
    	push     ds
    	push     es
    	push     si
    	push     di
    	
    	call	IntTimer		;cpu independant interrupt timer
    	call	DeadMan			;deadman relay driver
    	call    inhand          ;update inputs
    	call	ButtonHandler	;Pb interlock handler
    	call	MandStop		;stop mandrel on switch
    	call	PDPress			;Pressure die pressure handler
    	call    DMCInt          ;DMC comms
    	call  	ophand          ;update outputs
    
    	 ; allow for speeded up clock
    
    	dec     cs:counter              ;count down
    	jns     exit                    ;not time yet
    	
    	; this section runs every eigth interrupt
    
    	mov     cs:counter,63            ;restart timer
    	
    	dec		cs:SecTimer		;update seconds counter
    	jns		@F
    	
    	mov		cs:sectimer,18		;restart seconds timer
    	call	ScreenTimer		;do this once per second
    	call	PumpTimer
    @@:
    	pop      di
    	pop      si
    	pop      es                      ;restore registers
    	pop      ds
    	popa
    	jmp      cs:oldvec               ;to normal clock interrupt
      
    exit:  
    	mov      al,20h                  ;issue an EOI
    	out      20h,al
    	
    	pop      di
    	pop      si
    	pop      es                      ;restore registers
    	pop      ds
    	popa
    	iret                            ;return from interrupt
    
    oldvec  dd      0
    counter dw      0
    SecTimer dw	18			;one second(approx) timer
    		 
    newint  endp
    	end
    
    
  • kwinnkwinn Posts: 8,697
    edited 2015-04-03 11:10
    Am I alone in thinking this train derailed many posts back and the individual cars are now merrily rolling down hill?

    Debates on things like the best computer language, religion, and philosophy are an endless quagmire of opinion and beliefs with virtually no facts to justify them.
  • mindrobotsmindrobots Posts: 6,506
    edited 2015-04-03 11:41
    kwinn wrote: »
    Am I alone in thinking this train derailed many posts back and the individual cars are now merrily rolling down hill?

    Not at all!! I'm enjoying it all from the club car!

    attachment.php?attachmentid=113757&d=1428086272
    271 x 186 - 12K
  • 4x5n4x5n Posts: 745
    edited 2015-04-03 12:07
    Mickster wrote: »
    @CuriousOne

    "can anyone provide live example?".....11 pages in and apparently not!

    VB and VC are "off topic" but apparently Scheme/Lisp/Pascal are on topic (I must be misinterpreting the title again)

    We have one who makes claims that C will "blow the pants off Basic" but can't tell us how/why. I guess he just read it somewhere.

    The statement was made: "Also, what your program does not use does not get linked in, that's great when you want tiny code." So I provided a compiled Windows BASIC "Hello World" that is ~8KB (no dependencies) and it fell on deaf ears.

    A data structure example written in C was used as an example of something that couldn't be done in BASIC. It took like 15mins (I'm slow on the keyboard) to replicate it using a 28 year old DOS BASIC and the bonus was improved readability.

    I think that the source code for linux was mentioned a time or two. It hasn't been posted but I don't think the moderators will allow it all to be posted here! :) For those interested in wading through the source code could consider the source to Xwindows and emacs.
  • mindrobotsmindrobots Posts: 6,506
    edited 2015-04-03 12:23
    CHeesecake BASIC - BASIC interpreter written in QuickBasic


    A tiny BASIC written in Pascal
    {******************************************************************************
    *                                                                             *
    *                            TINY PASCAL BASIC                                *
    *                                                                             *
    *                            1980 S. A. MOORE                                 *
    *                                                                             *
    * Implements a small basic in Pascal. An example of how small a program can   *
    * be to implement a simple language.                                          *
    * Variables are allowed, using the letters "a" thru "z". Integers are denoted *
    * by the letters alone. Strings are denoted by "a$" form.                     *
    * The following statements are implemented:                                   *
    *                                                                             *
    *    input <variable>   Reads the contents of the variable from the user.     *
    *                       If the variable is integer, a line is read from the   *
    *                       user, then any spaces on the line skipped, then a     *
    *                       number read.                                          *
    *                       If the variable is string, the entire line is         *
    *                       assigned to it, including any spaces.                 *
    *                                                                             *
    *    print <expr> [,<expr].. [;] Prints the expression. The expression can be *
    *                       integer or string. If a trailing ";" exists, the next *
    *                       print will resume on the same line. Any number of     *
    *                       items may appear to be printed on the same line,      *
    *                       separated by ",".                                     *
    *                                                                             *
    *    goto <integer>     Control resumes at the line specified by the integer. *
    *                       Note that no "calculated gotos" are allowed.          *
    *                                                                             *
    *    if <expr> then <statement>  The expression must be a integer. If the     *
    *                       condition is 0, control resumes on the next line.     *
    *                       if the condition is not 0, the statement after "then" *
    *                       is executed (as well as the rest of the line).        *
    *                                                                             *
    *    rem <line>         The entire rest of the line is ignored.               *
    *                                                                             *
    *    stop               Terminates program execution. The values of variables *
    *                       are not cleared.                                      *
    *                                                                             *
    *    run                All variables are cleared, with integers becoming 0,  *
    *                       and strings becoming empty. Then control passes to    *
    *                       the first statement in the program.                   *
    *                                                                             *
    *    list [<start>[,<end>]]  Lists all program lines between the given lines. *
    *                       The default if no lines are given is the starting     *
    *                       and ending lines of the entire program.               *
    *                                                                             *
    *    new                Clears the entire program and stops execution.        *  
    *                                                                             *
    *    [let] <var> = <expr>  Assigns the value of the expression to the         *
    *                       variable. The variable must be the same type (string  *
    *                       or integer) as the expression. The "let" keyword is   *
    *                       optional.                                             *
    *                                                                             *
    *    bye                Exits basic for the operating system.                 *
    *                                                                             *
    * Expressions can contain the following operators:                            *
    *                                                                             *
    *    <, >, =, <>, <=, >=          Comparision.                                *
    *    +, -, *, /, mod              Basic math.                                 *
    *    left$(<str>, <expr>)         The leftmost characters of the string.      *
    *    right$(<str>, <expr>)        The rightmost characters of the string.     *
    *    mid$(<str>, <start>, <len>)  The middle characters of the string.        *
    *    str$(<expr>)                 The string form of the integer expression.  *
    *    val(<str>)                   The integer equivalent of the string.       *
    *    chr(<str>)                   The ascii value of the first character.     *
    *                                                                             *
    * The internal form of the program is keyword compressed for effiency, which  *
    * both allows for a smaller internal program, and simplifies the decoding of  *
    * keywords.                                                                   *
    *                                                                             *
    *                                                                             *
    * Notes:                                                                      *
    *                                                                             *
    * 1. If the program store were of the same form as basic strings, routines    *
    * that handle both in common could be used (example: getting a number from    *
    * the string).                                                                *
    *                                                                             *
    ******************************************************************************}
    
    program basics(input, output);
    
    label   88, 77, 99;
     
    const   maxlin = 9999; { maximum line number }
            maxpgm = 100;  { maximum line store }
            maxstk = 10;   { maximum temp count }
            maxkey = 29;   { maximum key store }
     
            { key codes }
     
            cinput =  1; cprint =  2; cgoto  =  3; cif    =  4;
            crem   =  5; cstop  =  6; crun   =  7; clist  =  8; 
            cnew   =  9; clet   = 10; cbye   = 11; clequ  = 12;
            cgequ  = 13; cequ   = 14; cnequ  = 15; cltn   = 16;
            cgtn   = 17; cadd   = 18; csub   = 19; cmult  = 20;
            cdiv   = 21; cmod   = 22; cleft  = 23; cright = 24;
            cmid   = 25; cthen  = 26; cstr   = 27; cval   = 28;
            cchr   = 29;
     
    type    string10   = packed array [1..10] of char;   { key }
            string80   = packed array [1..80] of char;   { general string }
            bstring80  = record
                           len : integer;
                           str : string80
                        end;
            vartyp     = (tint, tstr); { variable type }
            { error codes }
            errcod     = (eitp, estate, eexmi, eeque, estyp, epbful, eiovf, evare,
                          elabnf, einte, econv, elntl, ewtyp, erpe, eexc, emqu, 
                          eifact, elintl, estrovf, eedlexp, elpe, ecmaexp, estre,
                          estrinx);
     
    var     prgm:  array [0..maxpgm] of string80; { program store }
            strs:  array ['a'..'z'] of bstring80;  { string store }
            ints:  array ['a'..'z'] of integer;   { integer store }
            keywd: array [cinput..cchr] of string10; { keywords }
            temp:  array [1..maxstk] of record
                                            typ  : vartyp;
                                            int  : integer;
                                            bstr : bstring80
                                         end;
            prgmc,           { program counter (0 = input line) }
            top,             { current temps top }
            linec: integer;  { character position }
    
    { print key compressed line }
     
    procedure prtlin(var str : string80);
     
    var i, j: integer;
     
    procedure prtkey(var str : string10);
     
    var i, j: integer;
     
    begin { prtkey }
    
       j := 10;
       while (str[j] = ' ') and (j > 0) do j := j - 1;
       j := j + 1;
       i := 1;
       while i < j do begin write(str[i]); i := i + 1 end
    
    end; { prtkey }
     
    begin { prtlin }
    
       j := 80;
       while (str[j] = ' ') and (j > 0) do j := j - 1;
       j := j + 1;
       i := 1;
       while i < j do begin
    
          if ord(str[i]) < ord(' ') then prtkey(keywd[ord(str[i])])
          else write(str[i]);
          i := i + 1
    
       end;
       writeln
    
    end; { prtlin }
    
    { print error }
     
    procedure prterr(err : errcod);
     
    begin
    
       if prgmc <> 0 then prtlin(prgm[prgmc]);
       write('*** ');
       case err of
     
          eitp:     writeln('Interpreter error');
          estate:   writeln('Statement expected');
          eexmi:    writeln('Expression must be integer');
          eeque:    writeln('"=" expected');
          estyp:    writeln('Operands not of same type');
          epbful:   writeln('Program buffer full');
          eiovf:    writeln('Input overflow');
          evare:    writeln('Variable expected');
          elabnf:   writeln('Statement label not found');
          einte:    writeln('Integer expected');
          econv:    writeln('Conversion error');
          elntl:    writeln('Line number too large');
          ewtyp:    writeln('Operand(s) of wrong type');
          erpe:     writeln('")" expected');
          eexc:     writeln('Expression too complex');
          emqu:     writeln('Missing quote');
          eifact:   writeln('Invalid factor');
          elintl:   writeln('Line number too large');
          estrovf:  writeln('String overflow');
          eedlexp:  writeln('End of line expected');
          elpe:     writeln('"(" expected');
          ecmaexp:  writeln('"," expected');
          estre:    writeln('String expected');
          estrinx:  writeln('String indexing error')
     
       end;
       goto 88 { loop to ready }
    
    end;
    
    { check character }
     
    function chkchr : char;
     
    var c: char;
     
    begin
    
       if linec <= 80 then c := prgm[prgmc][linec]
       else c := ' ';
       chkchr := c
    
    end;
    
    { check end of line }
    
    function chkend: boolean;
    
    begin
    
       chkend := linec > 80 { past end of line }
    
    end;
     
    { get character }
     
    function getchr: char;
     
    begin
    
       getchr := chkchr;
       if not chkend then linec := linec + 1
    
    end;
     
    { check next character }
     
    function chknxt(c : char) : boolean;
     
    begin
    
       chknxt := c = chkchr;
       if c = chkchr then c := getchr
    
    end;
     
    { skip spaces }
     
    procedure skpspc;
     
    var c: char;
     
    begin
    
       while (chkchr = ' ') and not chkend do c := getchr;
    
    end;
    
    { check end of statement }
    
    function chksend: boolean;
    
    begin
    
       skpspc; { skip spaces }
       chksend := chkend or (chkchr = ':') { check eoln or ':' }
    
    end;
    
    { check null string }
     
    function null(var str : string80) : boolean;
     
    var i: integer;
        f: boolean;
     
    begin
    
       f := true;
       for i := 1 to 80 do if str[i] <> ' ' then f := false;
       null := f
    
    end;
     
    { check digit }
     
    function digit(c : char) : boolean;
     
    begin
    
       digit := (ord(c) >= ord('0')) and (ord(c) <= ord('9'))
    
    end;
     
    { convert to lower case }
     
    function lcase(c : char) : char;
     
    begin
    
       if (ord(c) >= ord('A')) and (ord(c) <= ord('Z')) then
          c := chr(ord(c) - ord('A') + ord('a'));
       lcase := c
    
    end;
     
    { check alphabetical }
     
    function alpha(c : char) : boolean;
     
    begin
    
       alpha := (ord(lcase(c)) >= ord('a')) and
          (ord(c) <= ord('z'))
    
    end;
    
    { parse leading integer }
     
    function lint(var str : string80) : integer;
     
    var i, v: integer;
        b:    boolean;
     
    begin
    
       v := 0;
       i := 1;
       while (i < 80) and (str[i] = ' ') do i := i + 1;
       repeat
    
          if digit(str[i]) then begin
    
             v := v*10 + (ord(str[i]) - ord('0'));
             if i <> 80 then begin
    
                i := i + 1;
                b := false
    
             end else b := true
    
          end else b := true
    
       until b;
       lint := v
    
    end;
    
    { search label }
     
    function schlab(lab : integer):integer;
     
    var i: integer;
     
    begin
    
       i := 1;
       while (lab <> lint(prgm[i])) and (i <= maxpgm) do i := i + 1;
       if lab <> lint(prgm[i]) then prterr(elabnf);
       schlab := i
    
    end;
     
    { input string }
     
    procedure inpstr(var str : string80);
     
    var i: integer;
     
    begin
    
       for i := 1 to 80 do str[i] := ' ';
       i := 1;
       while (i <= 80) and not eoln do begin
    
          read(str[i]);
          i := i + 1
    
       end;
       readln;
       if (i > 80) then prterr(eiovf)
    
    end;
     
    { parse variable reference }
     
    function getvar : char;
     
    begin
    
       if not alpha(chkchr) then prterr(evare);
       getvar := lcase(getchr)
    
    end;
    
    { enter line to store }
     
    procedure enter(var str : string80);
     
    var line, i, j, k: integer;
        f:             boolean;
     
    begin
    
       line := lint(str);
       if line > maxlin then prterr(elintl); { input line number to large }
       i := 1;
       f := false;
       repeat
    
          if null(prgm[i]) then f := true
          else if lint(prgm[i]) < line then begin
    
             i := i + 1;
             if i > maxpgm then f := true
    
          end else f := true
    
       until f;
       if i > maxpgm then prterr(epbful);
       if null(prgm[i]) then prgm[i] := str
       else if lint(prgm[i]) = line then begin
    
          j := 1;
          while (str[j] = ' ') and (j < 80) do j := j + 1;
          while digit(str[j]) and (j < 80) do j := j + 1;
          while (str[j] = ' ') and (j < 80) do j := j + 1;
          if j = 80 then begin
    
             for k := i to maxpgm - 1 do prgm[k] := prgm[k + 1];
             for j := 1 to 80 do prgm[maxpgm][j] := ' '
    
          end else prgm[i] := str
    
       end else if not null(prgm[maxpgm]) then prterr(epbful)
       else begin
    
          for k := maxpgm downto i + 1 do prgm[k] := prgm[k - 1];
          prgm[i] := str
    
       end
    
    end;
    
    { compress keys }
     
    procedure keycom(var str : string80);
     
    var ts:        string80;
        k, i1, i2: integer;
        f:         boolean;
        c:         char;
     
    function matstr(var stra: string80; var i: integer;
                     var strb: string10): boolean;
     
    var i1, i2: integer;
        f:      boolean;
     
    begin { matstr }
    
       i1 := i;
       i2 := 1;
       repeat
    
          if strb[i2] = ' ' then f := false
          else if lcase(stra[i1]) = lcase(strb[i2]) then begin
    
             f := true;
             i1 := i1 + 1;
             i2 := i2 + 1
    
          end
          else f := false
    
       until not f or (i1 > 80) or (i2 > 10);
       if i2 > 10 then begin f := true; i := i1 end
       else if strb[i2] = ' ' then begin f := true; i := i1 end
       else f := false;
       matstr := f
    
    end; { matstr }
    {}
    begin { keycom }
    
       for i2 := 1 to 80 do ts[i2] := ' ';
       i1 := 1;
       i2 := 1;
       repeat
    
          if str[i1] = '"' then begin
    
             ts[i2] := '"';
             i1 := i1 + 1;
             i2 := i2 + 1;
             c := ' ';
             while (i1 <= 80) and (c <> '"') do begin
    
                c := str[i1];
                ts[i2] := str[i1];
                i1 := i1 + 1;
                i2 := i2 + 1
    
             end
    
          end else if str[i1] = ' ' then begin
    
             ts[i2] := str[i1];
             i1 := i1 + 1;
             i2 := i2 + 1
    
          end else begin
    
             k := 1;
             f := false;
             while (k <= maxkey) and not f do
             begin
    
                f := matstr(str, i1, keywd[k]);
                k := k + 1
    
             end;
             if f then ts[i2] := chr(k - 1)
             else begin ts[i2] := str[i1]; i1 := i1 + 1 end;
             i2 := i2 + 1
    
          end
    
       until i1 > 80;
       for i1 := 1 to 80 do str[i1] := ts[i1]
    { this diagnostic prints the resulting tolken sequence }
    {;for i1 := 1 to 80 do write(ord(str[i1]), ' ');}
    
    end; { keycom }
    
    { get integer }
     
    function getint: integer;
     
    var v: integer;
     
    begin
    
       v := 0;
       skpspc;
       if not digit(chkchr) then prterr(einte);
       repeat v := v*10 + (ord(getchr) - ord('0'))
       until not digit(chkchr);
       getint := v
    
    end;
     
    { get integer from string }
     
    function getval(var str: string80): integer;
     
    var i: integer;
     
    begin
    
       i := 1;
       while (i <= 80) and (str[i] = ' ') do i := i + 1;
       if not digit(str[i]) then prterr(einte);
       getval := lint(str);
       while (i < 80) and digit(str[i]) do i := i + 1;
       while (i < 80) and (str[i] = ' ') do i := i + 1;
       if i <> 80 then prterr(econv)
    
    end;
    
    { get integer from basic string }
     
    function getbval(var str: bstring80): integer;
     
    var i, v: integer;
     
    begin
    
       i := 1;
       while (i <= str.len) and (str.str[i] = ' ') do i := i + 1; { skip spaces }
       if not digit(str.str[i]) then prterr(einte); { number not present }
       v := 0; { clear result }
       while (i <= str.len) and digit(str.str[i]) do begin { parse digit }
    
          v := v*10+ord(str.str[i])-ord('0'); { scale, convert and add in digit }
          i := i+1 { next character }
    
       end;
       while (i <= str.len) and (str.str[i] = ' ') do i := i + 1;
       if i <= str.len then prterr(econv);
       getbval := v { return result }
    
    end;
    
    { place integer to string }
    
    procedure putbval(var str: bstring80; v: integer);
    
    var p: integer; { power holder }
        i: integer; { string index }
    
    begin
    
       str.len := 0; { clear result string }
       p := 10000; { set maximum power }
       i := 1; { set 1st character }
       if v < 0 then begin { negative }
    
          str.str[i] := '-'; { place minus sign }
          i := i + 1; { next character }
          v := -v { negate number }
    
       end;
       while p <> 0 do begin { fit powers }
    
          str.str[i] := chr(v div p+ord('0')); { place digit }
          if str.str[1] = '-' then begin { negative }
    
             if (str.str[2] <> '0') or (p = 1) then i := i + 1; { next digit }
    
          end else { positive }
             if (str.str[1] <> '0') or (p = 1) then i := i + 1; { next digit }
          v := v mod p; { remove from value }
          p := p div 10 { find next power }
    
       end;
       str.len := i-1 { set length of string }
    
    end;
    
    { print basic string }
     
    procedure prtbstr(var bstr: bstring80);
     
    var i: integer;
     
    begin
    
       for i := 1 to bstr.len do write(bstr.str[i]);
    
    end;
     
    { input basic string }
     
    procedure inpbstr(var bstr: bstring80);
     
    var i: integer;
     
    begin
    
       for i := 1 to 80 do bstr.str[i] := ' ';
       i := 1;
       while (i < 80) and not eoln do begin
    
          read(bstr.str[i]);
          i := i + 1
    
       end;
       if (i > 80) and not eoln then prterr(eiovf);
       readln;
       bstr.len := i
    
    end;
     
    { concatenate basic strings }
     
    procedure cat(var bstra, bstrb: bstring80);
     
    var i: integer; { index for string }
    
    begin 
    
       if (bstra.len + bstrb.len) > 80 then prterr(estrovf); { string overflow }
       { copy source after destination }
       for i := 1 to bstrb.len do bstra.str[bstra.len+i] := bstrb.str[i];
       bstra.len := bstra.len + bstrb.len { set new length }
    
    end;
    
    { check stack items equal }
     
    function chkequ : boolean;
     
    begin
    
       if (temp[top].typ <> tint) or (temp[top - 1].typ <> tint) then 
          prterr(ewtyp);
       chkequ := temp[top - 1].int = temp[top].int
    
    end;
     
    { check stack items less than }
     
    function chkltn: boolean;
     
    begin
    
       if (temp[top].typ <> tint) or (temp[top - 1].typ <> tint)
          then prterr(ewtyp);
       chkltn := temp[top - 1].int < temp[top].int
    
    end;
     
    { check stack items greater than }
     
    function chkgtn: boolean;
     
    begin
    
       if (temp[top].typ <> tint) or (temp[top - 1].typ <> tint)
          then prterr(ewtyp);
       chkgtn := temp[top - 1].int > temp[top].int
    
    end;
     
    { set tos true }
     
    procedure settrue;
     
    begin
    
       temp[top].typ := tint;
       temp[top].int := 1
    
    end;
     
    { set tos false }
     
    procedure setfalse;
     
    begin
    
       temp[top].typ := tint;
       temp[top].int := 0
    
    end;
    
    { clear program store }
     
    procedure clear;
     
    var x, y: integer;
        c:    char;
     
    begin
    
       for x := 1 to maxpgm do
          for y := 1 to 80 do prgm[x][y] := ' ';
       for c := 'a' to 'z' do strs[c].len := 0;
       for c := 'a' to 'z' do ints[c] := 0;
       prgmc := 0;
       linec := 1;
       top := 1
    
    end;
     
    { clear variable store }
     
    procedure clrvar;
     
    var c: char;
     
    begin
    
       for c := 'a' to 'z' do strs[c].len := 0;
       for c := 'a' to 'z' do ints[c] := 0;
       prgmc := 0;
       linec := 1;
       top := 1
    
    end;
    
    { execute string }
     
    procedure exec;
     
    label 1; { exit procedure }
     
    var c: char;
     
    { execute statement }
     
    procedure stat;
     
    var x, y: integer;
        c:    char;
        s:    string80;
        b:    boolean;
     
    { parse expression }
     
    procedure expr;
     
    { parse simple expression }
     
    procedure sexpr;
     
    { parse term }
     
    procedure term;
     
    { parse factor }
     
    procedure factor;
     
    var i: integer;
        c: char;
    
    begin { factor }
    
       skpspc;
       c := chkchr; { save starting character }
       if chknxt('(') then begin
    
          expr;
          if not chknxt(')') then prterr(erpe)
    
       end else if chknxt(chr(cadd)) then begin
    
          factor;
          if temp[top].typ <> tint then prterr(ewtyp)
    
       end else if chknxt(chr(csub)) then begin
    
          factor;
          if temp[top].typ <> tint then prterr(ewtyp);
          temp[top].int := - temp[top].int
    
       end else if chknxt('"') then begin
    
          top := top + 1;
          if top > maxstk then prterr(eexc);
          temp[top].typ := tstr;
          i := 1;
          while (i <= 80) and (chkchr <> '"') do begin
    
             temp[top].bstr.str[i] := getchr;
             i := i + 1
    
          end;
          if not chknxt('"') then prterr(emqu);
          temp[top].bstr.len := i - 1
    
       end else if digit(chkchr) then begin
    
          top := top + 1;
          if top > maxstk then prterr(eexc);
          temp[top].typ := tint;
          temp[top].int := getint
    
       end else if alpha(chkchr) then begin
    
          top := top + 1;
          if top > maxstk then prterr(eexc);
          c := getvar;
          if chknxt('$') then begin
    
             temp[top].typ := tstr;
             temp[top].bstr := strs[c]
    
          end else begin
    
             temp[top].typ := tint;
             temp[top].int := ints[c]
    
          end
    
       end else if chknxt(chr(cleft)) or chknxt(chr(cright)) or 
                   chknxt(chr(cmid)) then begin
    
          { left$, right$ }
          skpspc; { skip spaces }
          if not chknxt('(') then prterr(elpe); { '(' expected }
          expr; { parse expression }
          if temp[top].typ <> tstr then prterr(estre); { string expected }
          skpspc; { skip spaces }
          if not chknxt(',') then prterr(ecmaexp); { ',' expected }
          expr; { parse expression }
          if temp[top].typ <> tint then prterr(einte); { integer expected }
          skpspc; { skip spaces }
          if c <> chr(cmid) then begin { left$ or right$ }
    
             if not chknxt(')') then prterr(erpe); { ')' expected }
             if temp[top].int > temp[top-1].bstr.len then prterr(estrinx);
             if c = chr(cright) then { right$ }
                for i := 1 to temp[top].int do { move string left }
                   temp[top-1].bstr.str[i] := 
                      temp[top-1].bstr.str[i+temp[top-1].bstr.len-temp[top].int];
             temp[top-1].bstr.len := temp[top].int; { set new length left }
             top := top-1 { clean stack }
    
          end else begin { mid$ }
    
             if not chknxt(',') then prterr(ecmaexp); { ',' expected }
             expr; { parse end expression }
             if temp[top].typ <> tint then prterr(einte); { integer expected }
             skpspc; { skip spaces }
             if not chknxt(')') then prterr(erpe); { ')' expected }
             { check requested length > string length }
             if temp[top].int+temp[top-1].int-1 > temp[top-2].bstr.len then 
                prterr(estrinx);
             for i := 1 to temp[top].int do { move string left }
                temp[top-2].bstr.str[i] := temp[top-2].bstr.str[i+temp[top-1].int-1];
             temp[top-2].bstr.len := temp[top].int; { set new length left }
             top := top-2 { clean stack }
    
          end
        
       end else if chknxt(chr(cchr)) then begin { chr }
    
          if not chknxt('(') then prterr(elpe); { '(' expected }
          expr; { parse expression }
          if temp[top].typ <> tstr then prterr(estre); { string expected }
          skpspc; { skip spaces }
          if not chknxt(')') then prterr(erpe); { ')' expected }
          if temp[top].bstr.len < 1 then prterr(estrinx); { check valid }
          c := temp[top].bstr.str[1]; { get the 1st character }
          temp[top].typ := tint; { change to integer }
          temp[top].int := ord(c) { place result }
    
       end else if chknxt(chr(cval)) then begin { val }
    
          if not chknxt('(') then prterr(elpe); { '(' expected }
          expr; { parse expression }
          if temp[top].typ <> tstr then prterr(estre); { string expected }
          skpspc; { skip spaces }
          if not chknxt(')') then prterr(erpe); { ')' expected }
          i := getbval(temp[top].bstr); { get string value }
          temp[top].typ := tint; { change to integer }
          temp[top].int := i { place result }
    
       end else if chknxt(chr(cstr)) then begin { str$ }
    
          if not chknxt('(') then prterr(elpe); { '(' expected }
          expr; { parse expression }
          if temp[top].typ <> tint then prterr(einte); { integer expected }
          skpspc; { skip spaces }
          if not chknxt(')') then prterr(erpe); { ')' expected }
          i := temp[top].int; { get value }
          temp[top].typ := tstr; { change to string }
          putbval(temp[top].bstr, i) { place value in ascii }
    
       end else prterr(eifact)
    
    end; { factor }
    
    begin { term }
    
       factor;
       skpspc;
       while ord(chkchr) in [cmult, cdiv, cmod] do begin
    
          case ord(getchr) of { tolken }
    
             cmult: begin { * }
       
                factor;
                if (temp[top].typ <> tint) or
                   (temp[top - 1].typ <> tint) then prterr(ewtyp);
                temp[top - 1].int := temp[top - 1].int * temp[top].int;
                top := top - 1
    
             end;
       
             cdiv: begin { / }
       
                factor;
                if (temp[top].typ <> tint) or
                   (temp[top - 1].typ <> tint) then prterr(ewtyp);
                temp[top - 1].int := temp[top - 1].int div temp[top].int;
                top := top - 1
    
             end;
       
             cmod: begin { mod }
       
                factor;
                if (temp[top].typ <> tint) or
                   (temp[top - 1].typ <> tint) then prterr(ewtyp);
                temp[top - 1].int := temp[top - 1].int mod
                   temp[top].int;
                top := top - 1
    
             end
    
          end;
          skpspc { skip spaces }
    
       end
    
    end; { term }
    
    begin { sexpr }
    
       term;
       skpspc;
       while ord(chkchr) in [cadd, csub] do begin
    
          case ord(getchr) of { tolken }
    
             cadd: begin
    
                term;
                if temp[top].typ = tstr then begin
       
                   if temp[top - 1].typ <> tstr then prterr(estyp);
                   cat(temp[top - 1].bstr, temp[top].bstr);
                   top := top - 1
       
                end else begin
       
                   if temp[top - 1].typ <> tint then prterr(estyp);
                   temp[top - 1].int :=
                      temp[top - 1].int + temp[top].int;
                   top := top - 1;
       
                end
    
             end;
       
             csub: begin { - }
       
                term;
                if (temp[top].typ <> tint) or
                   (temp[top - 1].typ <> tint) then prterr(ewtyp);
                temp[top - 1].int := temp[top - 1].int - temp[top].int;
                top := top - 1
       
             end
    
          end;
          skpspc { skip spaces }
    
       end
    
    end; { sexpr }
    
    begin { expr }
    
       sexpr; { parse simple expression }
       skpspc; { skip spaces }
       while ord(chkchr) in [cequ, cnequ, cltn, cgtn, clequ, cgequ] do begin
    
          case ord(getchr) of { tolken }
    
             cequ: begin
       
                sexpr;
                if chkequ then begin top := top - 1; settrue end
                else begin top := top - 1; setfalse end
       
             end;
       
             cnequ: begin
       
                sexpr;
                if chkequ then begin top := top - 1; setfalse end
                else begin top := top - 1; settrue end
       
             end;
       
             cltn: begin
       
                sexpr;
                if chkltn then begin top := top - 1; settrue end
                else begin top := top - 1; setfalse end
       
             end;
       
             cgtn: begin
       
                sexpr;
                if chkgtn then begin top := top - 1; settrue end
                else begin top := top - 1; setfalse end
       
             end;
       
             clequ: begin
       
                sexpr;
                if chkgtn then begin top := top - 1; setfalse end
                else begin top := top - 1; settrue end
       
             end;
    
             cgequ: begin
       
                sexpr;
                if chkltn then begin top := top - 1; setfalse end
                else begin top := top - 1; settrue end
       
             end
    
         end;
         skpspc { skip spaces }
    
       end
    
    end; { expr }
    
    { process "let" function }
    
    procedure let;
    
    begin
    
       skpspc;
       c := getvar;
       if chknxt('$') then begin
    
          skpspc;
          if not chknxt(chr(cequ)) then
             prterr(eeque);
          expr;
          if temp[top].typ <> tstr then
             prterr(estyp);
          strs[c] := temp[top].bstr;
          top := top - 1
    
       end else begin
    
          skpspc;
          if not chknxt(chr(cequ)) then
             prterr(eeque);
          expr;
          if temp[top].typ <> tint then
             prterr(estyp);
          ints[c] := temp[top].int;
          top := top - 1
    
       end
    
    end;
    
    begin { stat }
    
       skpspc;
       if ord(chkchr) < ord(' ') then begin
    
          if ord(chkchr) > cbye then prterr(estate);
          case ord(getchr) of { statement }
     
             cinput:  begin
    
                         skpspc;
                         c := getvar;
                         if chknxt('$') then inpbstr(strs[c])
                         else begin
    
                            inpstr(s);
                            ints[c] := getval(s)
    
                         end
    
                       end;
     
             cprint:   begin
    
                          repeat { list items }
    
                             expr;
                             if temp[top].typ = tstr then prtbstr(temp[top].bstr)
                             else write(temp[top].int);
                             top := top - 1;
                             skpspc
                          
                          until not chknxt(','); { until not ',' }
                          if not chknxt(';') then writeln
    
                        end;
     
             cgoto:     begin
    
                           prgmc := schlab(getint);
                           goto 1
    
                        end;
     
             cif:       begin
    
                           expr;
                           if temp[top].typ <> tint then
                              prterr(eexmi);
                           if temp[top].int = 0 then begin
    
                              top := top - 1;
                              { go next line }
                              if prgmc > 0 then prgmc := prgmc + 1;
                              goto 1
    
                           end;
                           top := top - 1;
                           b := chknxt(chr(cthen));
                           stat
    
                        end;
     
             crem:      begin
    
                           if prgmc > 0 then prgmc := prgmc + 1; { go next line }
                           goto 1 { exit line executive }
    
                        end;
     
             cstop:     goto 88;
     
             crun:      begin clrvar; prgmc := 1; goto 1 end;
     
             clist:     begin
    
                           x := 1; { set default list swath }
                           y := maxpgm;
                           if not chksend then begin { list swath is specified }
    
                              x := schlab(getint);
                              skpspc;
                              { check if end line is specified }
                              if chknxt(',') then y := schlab(getint)
    
                           end;
                           for x := x to y do { print specified lines }
                              if not null(prgm[x]) then { line exists in buffer }
                                 prtlin(prgm[x]) { print }
    
                        end;
     
             cnew:      begin clear; goto 88 end;
     
             clet:      let;
     
             cbye:      goto 99
     
          end
    
       end else let { default let }
    
    end; { stat }
    
    begin { exec }
    
       linec := 1;
       while digit(chkchr) do c := getchr; { skip label }
       repeat stat until getchr <> ':';
       skpspc;
       if not chkend then prterr(eedlexp); { should be at line end }
       if prgmc > 0 then prgmc := prgmc + 1;
       1:
    
    end; { exec }
    
    begin { executive }
    
       clear;
       { initalize keys }
       keywd[cinput] := 'input     '; keywd[cprint] := 'print     ';
       keywd[cgoto]  := 'goto      '; keywd[cif]    := 'if        ';
       keywd[crem]   := 'rem       '; keywd[cstop]  := 'stop      ';
       keywd[crun]   := 'run       '; keywd[clist]  := 'list      ';
       keywd[cnew]   := 'new       '; keywd[clet]   := 'let       ';
       keywd[cbye]   := 'bye       '; keywd[clequ]  := '<=        ';
       keywd[cgequ]  := '>=        '; keywd[cequ]   := '=         ';
       keywd[cnequ]  := '<>        '; keywd[cltn]   := '<         ';
       keywd[cgtn]   := '>         '; keywd[cadd]   := '+         ';
       keywd[csub]   := '-         '; keywd[cmult]  := '*         ';
       keywd[cdiv]   := '/         '; keywd[cmod]   := 'mod       ';
       keywd[cleft]  := 'left$     '; keywd[cright] := 'right$    ';
       keywd[cmid]   := 'mid$      '; keywd[cthen]  := 'then      ';
       keywd[cstr]   := 'str$      '; keywd[cval]   := 'val       ';
       keywd[cchr]   := 'chr       ';
       writeln;
       writeln('Tiny basic interpreter vs. 0.1 Copyright (C) 1994 S. A. Moore');
       writeln;
       88: while true do begin
    
          writeln('Ready');
       77: prgmc := 0;
          linec := 1;
          top := 0;
          { get user lines until non-blank }
          repeat inpstr(prgm[0]) until not null(prgm[0]);
          keycom(prgm[0]);
          if lint(prgm[0]) > 0 then begin
    
             enter(prgm[0]);
             goto 77
    
          end else repeat
    
             exec;
             if (prgmc > maxpgm) then prgmc := 0
             else if null(prgm[prgmc]) then prgmc := 0
    
          until prgmc = 0
    
       end;
       99: writeln
    
    end.
    
  • $WMc%$WMc% Posts: 1,884
    edited 2015-04-03 18:48
    Prop-Basic is super fast...
    '
    It compiles down into PASM.
    '
    This is as fast as you can go. No matter what code you write in.
    '
    The Simple IDE is a joke!!!
    '
    C , C+++ , C what ever needs so much user input. I just don't like to type that much.
    '
    Why Parallax bailed on Basic is beyond me????....This is what founded the company.
  • ercoerco Posts: 20,256
    edited 2015-04-03 19:08
    Horses for courses. Is vanilla better than chocolate?

    Are we almost done second-guessing each other here, or is this thread headed for Whit's "Most Viewed Thread" thread?

    I think this young thread definitely wins the "rate of viewing *& commenting" award anyway.
  • LoopyBytelooseLoopyByteloose Posts: 12,537
    edited 2015-04-04 07:01
    Wow, PropBasic compiles down to PASM! HOT DOG, I must try it.

    Regarding the biggest downside of C,
    there are some rather daunting formalities that the plain vanila beginner might become dismayed with.

    A. The Preprocessor
    B. Syntax Checking
    C. Object Code generation
    D. Linking

    All these steps have good reasons to exist. But for a begineer, there are more ways to mess up.

    In the beginning, too much formality will often chase away otherwise able learners. So why bother to load up the new student until they have ambitions for greater things.

    Heater may know a lot, but he certainly doesn't think like an educator. And when someone asked why Basic or C, I strongly suspect they are looking to begin learning --- not to add to their professional development.

    PropBasic might just appeal to the many users that have felt unable to grasp SPIN and Object Oriented Programing. SPIN is a great language, but it has scared off a lot of naive-but-willing-to-learn new users.

    So this is wonderful as Parallax is filling in the gaps in a solid pathway to learning towards becoming a pro.

    :-)

    Personally, I will never look at Pascal, and Lisp drove me crazy when I attempted to do so. They do have their uses, but either in history or advance study.
  • GenetixGenetix Posts: 1,754
    edited 2015-04-04 21:53
    BASIC is a lot easier for a non-programmer to read. (Excluding that MS stuff!)
    C is a much more powerful language but for what the average person will do BASIC gets the job done.
    C is also a lot more abstract and it lacks many of the convenience and safety features that BASIC has such as error checking and garbage collection.

    Careful where you stick that C pointer or you might crash your system.

    Loopy, I found Spin to very similar with PBASIC though there are some differences. I learned PASCAL after having learned BASIC and it made learning C a lot easier.
  • CuriousOneCuriousOne Posts: 931
    edited 2015-04-05 00:01
    When I was at high school, we had introductionary course for programming languages. I liked COBOL, since it looked like normal human readable code. And I disliked ALGOL, since it used a lot of non human friendly symbols such as &[]\">>> etc. Who knew then, that this junk going to grow and later give us Pascal and C :D
  • Heater.Heater. Posts: 21,230
    edited 2015-04-05 02:32
    CuriousOne,

    Now that is a step to far. One should not speak ill of the dead. ALGOL was a wonderful thing. The first language to properly express, indeed define, structured programming as we know it today. Even modern BASICS follow in the footsteps of ALGOL with their if/else, while, for, do, named functions, data structures etc, etc, etc.

    I'm not sure which ALGOL you were shown that was made ugly for you with &[]\">>> etc. I learned ALGOL as my third programming language and I don't recall having any such trouble. Mind you I don't remember much. I seem to recall it looked like this example for wikipedea:
    [B]procedure[/B] Absmax(a) Size:(n, m) Result:(y) Subscripts:(i, k);
        [B]value[/B] n, m; [B]array[/B] a; [B]integer[/B] n, m, i, k;[B] real[/B] y;
    [B]comment[/B] The absolute greatest element of the matrix a, of size n by m
        is transferred to y, and the subscripts of this element to i and k;
    [B]begin[/B]
        [B]integer[/B] p, q;
        y := 0; i := k := 1;
        [B]for[/B] p := 1 [B]step[/B] 1 [B]until[/B] n [B]do[/B]
            [B]for[/B] q := 1 [B]step[/B] 1 [B]until[/B] m do
                [B]if[/B] abs(a[p, q]) > y [B]then[/B]
                    [B]begin[/B] y := abs(a[p, q]);
                        i := p; k := q
                    [B]end[/B]
    [B]end[/B] [B]Absmax[/B]
    
    A thing of beauty.
  • CuriousOneCuriousOne Posts: 931
    edited 2015-04-05 03:47
    Well, that wikipedia example perfectly shows my understanding of "ugly":

    1. Why it has : in front of =
    2. Why some lines end with ;, while others - not
    3. "for p := 1 step 1 until n do" - what this line does, it is not possible to understand from human knowing of english language, while basic is much closer to "real" language in such constructions.
  • David BetzDavid Betz Posts: 14,516
    edited 2015-04-05 04:19
    CuriousOne wrote: »
    Well, that wikipedia example perfectly shows my understanding of "ugly":

    1. Why it has : in front of =
    2. Why some lines end with ;, while others - not
    3. "for p := 1 step 1 until n do" - what this line does, it is not possible to understand from human knowing of english language, while basic is much closer to "real" language in such constructions.
    It seems that your definition of "ugliness" is "anything that doesn't look exactly like Basic". Given that, there is no answer to your original question but "Basic". Now you have your answer so discussion can end.
Sign In or Register to comment.