; ( These macros make development easier. They provide a
;   layer of abstraction between Forth and the CPU. )

;---------------------------------------------------------------------
; Multiple push/pop
;	push eax,ebx,ecx...
;	pop eax,ebx,ecx...

%macro push 1-*.nolist
%rep %0
	push dword %1
%rotate 1
%endrep
%endmacro

%macro pop 1-*.nolist
%rep %0
%rotate -1
	pop dword %1
%endrep
%endmacro
%macro dup 0
        sub esi,byte 4
        mov [esi],eax
%endmacro
%macro drop 0
        lodsd
%endmacro
%macro variable 2
       call dovar
       %1 dd %2
%endmacro
%macro swap 0
       xchg eax,[esi]
%endmacro
%macro nip 0
       add esi,byte 4
%endmacro

%macro embed 1
   upsh %%e1
   upsh [%%e2]
   call eval	
   jmp short %%e3
%%e1 db %1
%%e2 dd $-%%e1
%%e3
%endmacro


%macro next 0
       ret
%endmacro

%macro upsh 1
        dup
        mov eax,%1
%endmacro
%macro upop 1
        mov %1,eax
        drop
%endmacro
;-------------------------------------------------------------------------
; Dictionary Macros (based on IsForth's)

%xdefine vlink 0            ;link to previous word in vocabulary
%xdefine forth_link 0       ;link to previous word in forth vocab
%xdefine macro_link 0       ;link to previous word in compiler vocab
%xdefine voc 0              ;currently linking to forth vocabulary

%macro header 2.nolist
%%link:
 dd vlink                   ;link to previous word in vocabulary
 dd %2                      ;pointer to cfa (in .text section)
 db (%%name-$-1)            ;name length + flags
 db %1                      ;name
%%name:
%xdefine vlink %%link
__SECT__
 forth                      ;Switch back to 'forth' vocab!!!
%endmacro

; Usage: code 'forth-name', asm-name
%macro code 2.nolist
 header %1,%2               ;create header in head space
%2:                         ;make label for new coded definition
%endmacro


; Usage: var 'name',name,value
%macro var 3.nolist
 code %1, ?%2
 call dovar
 %2 dd %3
%endmacro

; Usage: const 'name',name,value
%macro const 3.nolist
 code %1, ?%2
 call doconstant
 %2 dd %3
%endmacro

%macro save_link 0.nolist
 %if(voc = 0)               ;were we linking on the forth vocabulary ?
  %xdefine forth_link vlink ;yes - set new end of forth vocab
 %elif(voc = 1)             ;were we linking on the macro vocabulary ?
  %xdefine macro_link vlink ;yes - set new end of macro vocab
 %endif
%endmacro

; Link all new definitions to the forth vocabulary
%macro forth 0.nolist
 save_link                  ;save link address of previous vocabulary
 %xdefine vlink forth_link  ;start linking on forth vocabulary
 %define voc 0
%endmacro

; Link all new definitions to the compiler vocabulary
%macro macro 0.nolist
 save_link                  ;save link address of previous vocabulary
 %xdefine vlink macro_link  ;start linking on 'macro' vocabulary
 %define voc 1
%endmacro

%macro mcode 2.nolist
 macro
 code %1, %2
%endmacro

;=========================================================================
%macro $at 2	;$at x,y
	mov dword [xy], %2+(%1<<16)
%endmacro

%macro $color 1	;$color 14
	mov [fore],byte %1
%endmacro

%macro case 2
cmp eax, %1
jz .%2
%endmacro

; Usage: autoexec <label>
;  Calls the label at startup
%macro autoexec 1
	%ifndef autoexec_list
	  %xdefine autoexec_list %1
	%else
	  %xdefine autoexec_list autoexec_list,%1
	%endif
%endmacro

%macro inline 1-*.nolist
%rep %0
	upsh %1
	call comma1
%rotate 1
%endrep
%endmacro