mirror of
https://github.com/dschmenk/PLASMA.git
synced 2024-06-01 19:41:36 +00:00
613 lines
16 KiB
Plaintext
Executable File
613 lines
16 KiB
Plaintext
Executable File
include "inc/cmdsys.plh"
|
|
include "inc/args.plh"
|
|
include "inc/fileio.plh"
|
|
include "inc/longjmp.plh"
|
|
//
|
|
// Tokens
|
|
//
|
|
const ID_LEN = 32
|
|
const ID_TKN = $D6 // V
|
|
const CHR_TKN = $C3 // C
|
|
const INT_TKN = $C9 // I
|
|
const STR_TKN = $D3 // S
|
|
const EOL_TKN = $02
|
|
const EOF_TKN = $01
|
|
const ERR_TKN = $00
|
|
//
|
|
//Ternary operand operators
|
|
//
|
|
const TERNARY_TKN = $BF // ?
|
|
const TRIELSE_TKN = $DF // _
|
|
//
|
|
// Binary operand operators
|
|
//
|
|
const SET_TKN = $BD // =
|
|
const ADD_TKN = $AB // +
|
|
const SUB_TKN = $AD // -
|
|
const MUL_TKN = $AA // *
|
|
const DIV_TKN = $AF // /
|
|
const MOD_TKN = $A5 // %
|
|
const OR_TKN = $FC // |
|
|
const EOR_TKN = $DE // ^
|
|
const AND_TKN = $A6 // &
|
|
const SHR_TKN = $D2 // R
|
|
const SHL_TKN = $CC // L
|
|
const GT_TKN = $BE // >
|
|
const GE_TKN = $C8 // H
|
|
const LT_TKN = $BC // <
|
|
const LE_TKN = $C2 // B
|
|
const NE_TKN = $D5 // U
|
|
const EQ_TKN = $C5 // E
|
|
const LOGIC_AND_TKN = $CE // N
|
|
const LOGIC_OR_TKN = $CF // O
|
|
//
|
|
// Unary operand operators
|
|
//
|
|
const AT_TKN = $C0 // @
|
|
const DOT_TKN = $AE // .
|
|
const COLON_TKN = $BA // :
|
|
const NEG_TKN = $AD // -
|
|
const POUND_TKN = $A3 // #
|
|
const COMP_TKN = $FE // ~
|
|
const LOGIC_NOT_TKN = $A1 // !
|
|
const BPTR_TKN = $DE // ^
|
|
const WPTR_TKN = $AA // *
|
|
const PTRB_TKN = $D8 // X
|
|
const PTRW_TKN = $D7 // W
|
|
const INC_TKN = $C1 // A
|
|
const DEC_TKN = $C4 // D
|
|
const LAMBDA_TKN = $A6 // &
|
|
//
|
|
// Enclosure tokens
|
|
//
|
|
const OPEN_PAREN_TKN = $A8 // (
|
|
const CLOSE_PAREN_TKN = $A9 // )
|
|
const OPEN_BRACKET_TKN = $DB // [
|
|
const CLOSE_BRACKET_TKN = $DD // ]
|
|
//
|
|
// Misc. tokens
|
|
//
|
|
const COMMA_TKN = $AC // ,
|
|
//const COMMENT_TKN = $BB // //
|
|
const DROP_TKN = $BB
|
|
//
|
|
// Keyword tokens
|
|
//
|
|
const CONST_TKN = $80
|
|
const BYTE_TKN = $81
|
|
const WORD_TKN = $82
|
|
const IF_TKN = $83
|
|
const ELSEIF_TKN = $84
|
|
const ELSE_TKN = $85
|
|
const FIN_TKN = $86
|
|
const END_TKN = $87
|
|
const WHILE_TKN = $88
|
|
const LOOP_TKN = $89
|
|
const CASE_TKN = $8A
|
|
const OF_TKN = $8B
|
|
const DEFAULT_TKN = $8C
|
|
const ENDCASE_TKN = $8D
|
|
const FOR_TKN = $8E
|
|
const TO_TKN = $8F
|
|
const DOWNTO_TKN = $90
|
|
const STEP_TKN = $91
|
|
const NEXT_TKN = $92
|
|
const REPEAT_TKN = $93
|
|
const UNTIL_TKN = $94
|
|
const DEF_TKN = $95
|
|
const STRUC_TKN = $96
|
|
const SYSFLAGS_TKN = $97
|
|
const DONE_TKN = $98
|
|
const RETURN_TKN = $99
|
|
const BREAK_TKN = $9A
|
|
const CONT_TKN = $9B
|
|
const PREDEF_TKN = $9C
|
|
const IMPORT_TKN = $9D
|
|
const EXPORT_TKN = $9E
|
|
const INCLUDE_TKN = $9F
|
|
//
|
|
// Types
|
|
//
|
|
const GLOBAL_TYPE = $0000
|
|
const CONST_TYPE = $0001
|
|
const BYTE_TYPE = $0002
|
|
const WORD_TYPE = $0004
|
|
const VAR_TYPE = $0006 // (WORD_TYPE | BYTE_TYPE)
|
|
const FUNC_TYPE = $0008
|
|
const FUNC_CONST_TYPE = $0009
|
|
const ADDR_TYPE = $000E // (VAR_TYPE | FUNC_TYPE)
|
|
const LOCAL_TYPE = $0010
|
|
const BPTR_TYPE = $0020
|
|
const WPTR_TYPE = $0040
|
|
const PTR_TYPE = $0060 // (BPTR_TYPE | WPTR_TYPE)
|
|
const XBYTE_TYPE = $0022 // (BPTR_TYPE | BYTE_TYPE)
|
|
const XWORD_TYPE = $0044 // (WPTR_TYPE | WORD_TYPE)
|
|
const CONSTADDR_TYPE = $0061 // (CONST_TYPE | PTR_TYPE)
|
|
const STR_TYPE = $0080
|
|
const PREDEF_TYPE = $0100
|
|
const EXPORT_TYPE = $0200
|
|
const EXTERN_TYPE = $0400
|
|
const EXTACCESS_TYPE = $0800
|
|
const RELATIVE_TYPE = $8000
|
|
//
|
|
// Fixup flags mask
|
|
//
|
|
const RESOLVED_FIXUP = $01
|
|
const RELATIVE_FIXUP = $02
|
|
const MASK_FIXUP = $90
|
|
const WORD_FIXUP = $80
|
|
const BYTE_FIXUP = $00
|
|
const EXTERN_FIXUP = $10
|
|
//
|
|
// Keywords
|
|
//
|
|
byte keywrds = "IF", IF_TKN
|
|
byte = "TO", TO_TKN
|
|
byte = "IS", OF_TKN
|
|
byte = "OR", LOGIC_OR_TKN
|
|
byte = "FOR", FOR_TKN
|
|
byte = "FIN", FIN_TKN
|
|
byte = "DEF", DEF_TKN
|
|
byte = "END", END_TKN
|
|
byte = "AND", LOGIC_AND_TKN
|
|
byte = "NOT", LOGIC_NOT_TKN
|
|
byte = "RES", BYTE_TKN
|
|
byte = "VAR", WORD_TKN
|
|
byte = "WORD", WORD_TKN
|
|
byte = "CHAR", BYTE_TKN
|
|
byte = "BYTE", BYTE_TKN
|
|
byte = "ELSE", ELSE_TKN
|
|
byte = "NEXT", NEXT_TKN
|
|
byte = "WHEN", CASE_TKN
|
|
byte = "LOOP", LOOP_TKN
|
|
byte = "STEP", STEP_TKN
|
|
byte = "DONE", DONE_TKN
|
|
byte = "WEND", ENDCASE_TKN
|
|
byte = "DROP", DROP_TKN
|
|
byte = "CONST", CONST_TKN
|
|
byte = "STRUC", STRUC_TKN
|
|
byte = "ELSIF", ELSEIF_TKN
|
|
byte = "WHILE", WHILE_TKN
|
|
byte = "UNTIL", UNTIL_TKN
|
|
byte = "BREAK", BREAK_TKN
|
|
byte = "IMPORT", IMPORT_TKN
|
|
byte = "EXPORT", EXPORT_TKN
|
|
byte = "DOWNTO", DOWNTO_TKN
|
|
byte = "REPEAT", REPEAT_TKN
|
|
byte = "RETURN", RETURN_TKN
|
|
byte = "PREDEF", PREDEF_TKN
|
|
byte = "INCLUDE", INCLUDE_TKN
|
|
byte = "CONTINUE", CONT_TKN
|
|
byte = "SYSFLAGS", SYSFLAGS_TKN
|
|
byte = "OTHERWISE",DEFAULT_TKN
|
|
byte = $FF
|
|
//
|
|
// Mathematical ops
|
|
//
|
|
const bops_tblsz = 17 // minus 1
|
|
byte[] bops_tbl // Highest precedence
|
|
byte = MUL_TKN, DIV_TKN, MOD_TKN
|
|
byte = ADD_TKN, SUB_TKN
|
|
byte = SHR_TKN, SHL_TKN
|
|
byte = AND_TKN
|
|
byte = EOR_TKN
|
|
byte = OR_TKN
|
|
byte = GT_TKN, GE_TKN, LT_TKN, LE_TKN
|
|
byte = EQ_TKN, NE_TKN
|
|
// Lowest precedence
|
|
byte[] bops_prec // Highest precedence
|
|
byte = 1, 1, 1
|
|
byte = 2, 2
|
|
byte = 3, 3
|
|
byte = 4
|
|
byte = 5
|
|
byte = 6
|
|
byte = 7, 7, 7, 7
|
|
byte = 8, 8
|
|
// Lowest precedence
|
|
byte[16] opstack
|
|
byte[16] precstack
|
|
word opsp
|
|
word[16] valstack
|
|
byte[16] sizestack
|
|
byte[16] typestack
|
|
word valsp
|
|
//
|
|
// Code sequence shared with optimizer
|
|
//
|
|
include "toolsrc/codeseq.plh"
|
|
//
|
|
//
|
|
// Symbol table variables
|
|
//
|
|
struc t_id
|
|
word idval
|
|
word idtype
|
|
byte funcparms
|
|
byte funcvals
|
|
byte extnum
|
|
byte idname
|
|
end
|
|
//
|
|
// Generated code buffers
|
|
//
|
|
const OPSEQNUM = 256
|
|
const DFDNUM = 128
|
|
const TAGNUM = 1024
|
|
const FIXUPNUM = 2048
|
|
const MODDEPNUM = 8
|
|
const IDGLOBALSZ = 4096
|
|
const IDLOCALSZ = 512
|
|
const CASENUM = 64
|
|
word fixup_cnt, tag_cnt = -1
|
|
word dfd_tag, dfd_cnt
|
|
word fixup_tag, fixup_addr
|
|
word tag_addr, tag_type
|
|
word idglobal_tbl, idlocal_tbl
|
|
word pending_seq
|
|
word globals, lastglobal, lastglobalsize, lastlocal, savelast, savetbl
|
|
word dfd_num, tag_num, fixup_num, globalbufsz, localbufsz, codebufsz
|
|
word datasize, framesize, savesize
|
|
byte locals, savelocals
|
|
word codebuff, codeptr, entrypoint
|
|
word modsysflags
|
|
byte[16] moddep_tbl[MODDEPNUM]
|
|
byte moddep_cnt, def_cnt = 1
|
|
predef parse_mods
|
|
predef emit_pending_seq#0
|
|
//
|
|
// Module relocation base address
|
|
//
|
|
const RELADDR = $1000
|
|
//
|
|
// Exports for optimizer module
|
|
//
|
|
export word freeop_lst
|
|
export word optimize_seq
|
|
//
|
|
// Compiler flags
|
|
//
|
|
const OPTIMIZE = 1
|
|
const OPTIMIZE2 = 2
|
|
const NO_COMBINE = 4
|
|
const WARNINGS = 8
|
|
byte outflags
|
|
//
|
|
// ProDOS/SOS file references
|
|
//
|
|
byte refnum, srcref, incref
|
|
byte[32] srcfile, incfile, relfile, modfile
|
|
word parsefile // Pointer to current file
|
|
word srcline // Saved source line number
|
|
//
|
|
// Scanner variables
|
|
//
|
|
word instr
|
|
word inbuff
|
|
word scanptr
|
|
byte token = EOL_TKN
|
|
byte scanchr, tknlen
|
|
word tknptr, parserrln
|
|
word constval
|
|
word lineno
|
|
//
|
|
// Parser variables
|
|
//
|
|
const LVALUE = 0
|
|
const RVALUE = 1
|
|
const LAMBDANUM = 16
|
|
word strconstbuff
|
|
word strconstptr
|
|
byte infunc, inlambda
|
|
byte stack_loop
|
|
byte prevstmnt
|
|
word infuncvals
|
|
word break_tag
|
|
word cont_tag
|
|
byte lambda_cnt, lambda_num
|
|
byte[LAMBDANUM] lambda_cparms
|
|
word[LAMBDANUM] lambda_seq, lambda_tag
|
|
predef parse_constexpr#3, parse_expr(codeseq)#2, parse_lambda
|
|
byte bytesln = " bytes\n"
|
|
//
|
|
// Arg pointer
|
|
//
|
|
word arg, opt
|
|
//
|
|
// Long jump environment
|
|
//
|
|
word exit
|
|
//
|
|
// Error string flags
|
|
//
|
|
const ERR_DUP = $0001
|
|
const ERR_UNDECL = $0002
|
|
const ERR_INVAL = $0004
|
|
const ERR_MISS = $0008
|
|
const ERR_OVER = $0010
|
|
const ERR_CLOSE = $0020
|
|
const ERR_LOCAL = $0040
|
|
const ERR_GLOBAL = $0080
|
|
const ERR_CODE = $0100
|
|
const ERR_ID = $0200
|
|
const ERR_CONST = $0400
|
|
const ERR_INIT = $0800
|
|
const ERR_STATE = $1000
|
|
const ERR_FRAME = $2000
|
|
const ERR_TABLE = $4000
|
|
const ERR_SYNTAX = $8000
|
|
|
|
//=====================================
|
|
//
|
|
// PLASMA Compiler
|
|
//
|
|
//=====================================
|
|
|
|
//
|
|
// Lexical scanner helper for keyword/IDs
|
|
//
|
|
asm scanid(scanptr, keywrds)#3
|
|
!SOURCE "vmsrc/plvmzp.inc"
|
|
LDA ESTKL,X
|
|
STA DSTL
|
|
LDA ESTKH,X
|
|
STA DSTH
|
|
LDA ESTKL+1,X
|
|
STA ESTKL,X ; COPY OUTPUT SCANPTR
|
|
STA SRCL
|
|
LDA ESTKH+1,X
|
|
STA ESTKH,X
|
|
STA SRCH
|
|
DEX
|
|
LDA #$00
|
|
STA ESTKL,X ; CLEAR OUTPUT TOKEN
|
|
STA ESTKH,X
|
|
STA ESTKH+2,X ; CLEAR MSB OF SCANCHR
|
|
TAY
|
|
LDA (SRC),Y
|
|
AND #$7F
|
|
CMP #'a'
|
|
BCC +
|
|
CMP #'z'+1
|
|
BCS +
|
|
SBC #$1F
|
|
STA (SRC),Y
|
|
+ STA ESTKL+2,X ; SET SCANCHR
|
|
CMP #'_'
|
|
BEQ +
|
|
CMP #'A'
|
|
BCC SCANEX
|
|
CMP #'Z'+1
|
|
BCS SCANEX
|
|
+ LDA #$D6 ; ID_TKN
|
|
STA ESTKL,X ; SET OUTPUT TOKEN = ID_TKN
|
|
SCANID INY
|
|
LDA (SRC),Y
|
|
AND #$7F
|
|
BEQ ++
|
|
CMP #'a'
|
|
BCC +
|
|
CMP #'z'+1
|
|
BCS ++
|
|
SBC #$1F
|
|
STA (SRC),Y ; COPY UPPERCASE CHAR BACK TO ^SCANPTR
|
|
BNE SCANID
|
|
+ CMP #'_'
|
|
BEQ SCANID
|
|
CMP #'0'
|
|
BCC ++
|
|
CMP #'9'+1
|
|
BCC SCANID
|
|
CMP #'A'
|
|
BCC ++
|
|
CMP #'Z'+1
|
|
BCC SCANID
|
|
++ STY TMPL
|
|
TYA
|
|
LDY #$00
|
|
CLC
|
|
ADC SRCL
|
|
STA ESTKL+1,X ; UPDATE SCANPTR
|
|
BCC MATCHLEN
|
|
INC ESTKH+1,X
|
|
MATCHLEN LDA (DST),Y
|
|
CMP TMPL
|
|
BCS +
|
|
ADC #$02
|
|
ADC DSTL
|
|
STA DSTL
|
|
BCC MATCHLEN
|
|
INC DSTH
|
|
BNE MATCHLEN
|
|
+ BNE SCANEX ; NO KEY MATCH
|
|
TAY
|
|
DEY
|
|
INC DSTL
|
|
BNE MATCHKEY
|
|
INC DSTH
|
|
MATCHKEY LDA (SRC),Y
|
|
CMP (DST),Y
|
|
BNE NEXTKEY
|
|
DEY
|
|
BPL MATCHKEY
|
|
LDY TMPL
|
|
LDA (DST),Y
|
|
STA ESTKL,X ; SET OUTPUT TOKEN
|
|
SCANEX RTS
|
|
NEXTKEY LDY #$00
|
|
LDA TMPL
|
|
SEC
|
|
ADC DSTL
|
|
STA DSTL
|
|
BCC MATCHLEN
|
|
INC DSTH
|
|
BNE MATCHLEN
|
|
end
|
|
//
|
|
// Handy functions
|
|
//
|
|
def nametostr(namestr, len, strptr)#0
|
|
^strptr = len
|
|
memcpy(strptr + 1, namestr, len)
|
|
end
|
|
def putcurln#0
|
|
byte i
|
|
putln; puts(parsefile); putc('['); puti(lineno); puts("]\n")
|
|
puts(instr); putln
|
|
for i = tknptr - inbuff downto 1
|
|
putc(' ')
|
|
next
|
|
puts("^\n")
|
|
end
|
|
//
|
|
// Error handler
|
|
//
|
|
def exit_err(err)#0
|
|
byte i
|
|
|
|
puts("\nError:")
|
|
if err & ERR_DUP; puts("duplicate "); fin
|
|
if err & ERR_UNDECL; puts("undeclared "); fin
|
|
if err & ERR_INVAL; puts("invalid "); fin
|
|
if err & ERR_MISS; puts("missing "); fin
|
|
if err & ERR_OVER; puts("overflowed "); fin
|
|
if err & ERR_CLOSE; puts("closing "); fin
|
|
if err & ERR_LOCAL; puts("local "); fin
|
|
if err & ERR_GLOBAL; puts("global "); fin
|
|
if err & ERR_CODE; puts("code "); fin
|
|
if err & ERR_ID; puts("identifier "); fin
|
|
if err & ERR_CONST; puts("constant"); fin
|
|
if err & ERR_INIT; puts("initializer"); fin
|
|
if err & ERR_STATE; puts("statement"); fin
|
|
if err & ERR_FRAME; puts("frame"); fin
|
|
if err & ERR_TABLE; puts("table"); fin
|
|
if err & ERR_SYNTAX; puts("syntax"); fin
|
|
putcurln
|
|
if incref
|
|
fileio:close(incref) // Close include file if open
|
|
fin
|
|
fileio:close(srcref) // Close source file
|
|
throw(exit, TRUE)
|
|
end
|
|
//
|
|
// Warning
|
|
//
|
|
def parse_warn(msg)#0
|
|
if outflags & WARNINGS
|
|
puts("\nWarning:")
|
|
puts(msg)
|
|
putcurln
|
|
fin
|
|
end
|
|
//
|
|
// Include code to reduce size of this file
|
|
//
|
|
include "toolsrc/codegen.pla"
|
|
include "toolsrc/lex.pla"
|
|
include "toolsrc/parse.pla"
|
|
//
|
|
// Look at command line arguments and compile module
|
|
//
|
|
puts("PLASMA Compiler, Version 2.11\n")
|
|
arg = argNext(argFirst)
|
|
if ^arg and ^(arg + 1) == '-'
|
|
opt = arg + 2
|
|
while TRUE
|
|
if toupper(^opt) == 'O'
|
|
//
|
|
// Load optimizer module here
|
|
//
|
|
if cmdsys:modexec("CODEOPT") >= 0
|
|
outflags = outflags | OPTIMIZE
|
|
fin
|
|
if not (outflags & OPTIMIZE)
|
|
puts("\nOptimizer disabled\n")
|
|
fin
|
|
opt++
|
|
if ^opt == '2'
|
|
outflags = outflags | OPTIMIZE2
|
|
opt++
|
|
fin
|
|
elsif toupper(^opt) == 'N'
|
|
outflags = outflags | NO_COMBINE
|
|
opt++
|
|
elsif toupper(^opt) == 'W'
|
|
outflags = outflags | WARNINGS
|
|
opt++
|
|
else
|
|
break
|
|
fin
|
|
loop
|
|
arg = argNext(arg)
|
|
fin
|
|
if ^arg
|
|
strcpy(@srcfile, arg)
|
|
arg = argNext(arg)
|
|
if ^arg
|
|
strcpy(@relfile, arg)
|
|
else
|
|
strcpy(@relfile, @srcfile)
|
|
//
|
|
// Strip trailing extension
|
|
//
|
|
while relfile and relfile[relfile] <> '.'
|
|
relfile--
|
|
loop
|
|
if relfile; relfile--; fin // Strip '.'
|
|
if not relfile
|
|
//
|
|
// Copy default name over
|
|
//
|
|
strcpy(@relfile, "A.OUT")
|
|
fin
|
|
modfile = 0
|
|
for srcref = 1 to relfile
|
|
if relfile[srcref] == '/'
|
|
modfile = 0
|
|
else
|
|
modfile++
|
|
modfile[modfile] = toupper(relfile[srcref])
|
|
fin
|
|
next
|
|
fin
|
|
fin
|
|
if srcfile and relfile
|
|
fileio:iobufalloc(2) // Reserve two I/O buffers
|
|
srcref = fileio:open(@srcfile)
|
|
if srcref
|
|
fileio:newline(srcref, $7F, $0D)
|
|
refnum = srcref
|
|
parsefile = @srcfile
|
|
strconstbuff = heapalloc(80)
|
|
instr = cmdsys:cmdline
|
|
inbuff = instr + 1
|
|
scanptr = inbuff
|
|
*instr = NULL
|
|
exit = heapalloc(t_except)
|
|
if not except(exit)
|
|
//
|
|
// Parse source code module
|
|
//
|
|
parse_module
|
|
fileio:close(srcref)
|
|
//
|
|
// Write REL file
|
|
//
|
|
fileio:destroy(@relfile)
|
|
fileio:create(@relfile, $FE, $1000) // full access, REL file
|
|
srcref = fileio:open(@relfile)
|
|
if srcref
|
|
writemodule(srcref)
|
|
fileio:close(srcref)
|
|
else
|
|
puts("\nError opening: "); puts(@relfile); putln
|
|
fin
|
|
fin
|
|
else
|
|
puts("\nError opening: "); puts(@srcfile); putln
|
|
fin
|
|
else
|
|
puts("Usage:+PLASM [-[W][O[2]][N]] <src> [out]\n")
|
|
fin
|
|
done
|