of816/ofw/of/instance.fs

198 lines
6.0 KiB
Forth

\ *****************************************************************************
\ * Copyright (c) 2004, 2011 IBM Corporation
\ * All rights reserved.
\ * This program and the accompanying materials
\ * are made available under the terms of the BSD License
\ * which accompanies this distribution, and is available at
\ * http://www.opensource.org/licenses/bsd-license.php
\ *
\ * Contributors:
\ * IBM Corporation - initial implementation
\ ****************************************************************************/
db" OF instance support (c) IBM"
\ Support for device node instances.
0 VALUE my-self
A0 CONSTANT max-instance-size \ MAG: originally 400
STRUCT
/n FIELD instance>node
/n FIELD instance>parent
/n FIELD instance>args
/n FIELD instance>args-len
/n FIELD instance>size
/n FIELD instance>#units
/n FIELD instance>unit1 \ For instance-specific "my-unit"
/n FIELD instance>unit2
/n FIELD instance>unit3
/n FIELD instance>unit4
CONSTANT /instance-header
: >instance ( offset -- myself+offset )
my-self 0= ABORT" No instance!"
dup my-self instance>size @ >= ABORT" Instance access out of bounds!"
my-self +
;
: (create-instance-var) ( initial-value -- )
get-node
dup node>instance-size @ cell+ max-instance-size
>= ABORT" Instance is bigger than max-instance-size!"
dup node>instance-template @ ( iv phandle tmp-ih )
swap node>instance-size dup @ ( iv tmp-ih *instance-size instance-size )
dup , \ compile current instance ptr
swap 1 cells swap +! ( iv tmp-ih instance-size )
+ !
;
: create-instance-var ( "name" initial-value -- )
CREATE (create-instance-var) PREVIOUS
;
: (create-instance-buf) ( buffersize -- )
aligned \ align size to multiples of cells
dup get-node node>instance-size @ + ( buffersize' newinstancesize )
max-instance-size > ABORT" Instance is bigger than max-instance-size!"
get-node node>instance-template @ get-node node>instance-size @ +
over erase \ clear according to IEEE 1275
get-node node>instance-size @ ( buffersize' old-instance-size )
dup , \ compile current instance ptr
+ get-node node>instance-size ! \ store new size
;
: create-instance-buf ( "name" buffersize -- )
CREATE (create-instance-buf) PREVIOUS
;
VOCABULARY instance-words ALSO instance-words DEFINITIONS
: VARIABLE 0 create-instance-var DOES> [ here ] @ >instance ;
: VALUE create-instance-var DOES> [ here ] @ >instance @ ;
: DEFER 0 create-instance-var DOES> [ here ] @ >instance @ execute ;
: BUFFER: create-instance-buf DOES> [ here ] @ >instance ;
PREVIOUS DEFINITIONS
\ Save XTs of the above instance-words (put on the stack with "[ here ]")
CONSTANT <instancebuffer>
CONSTANT <instancedefer>
CONSTANT <instancevalue>
CONSTANT <instancevariable>
\ check whether a value or a defer word is an
\ instance word: It must be a CREATE word and
\ the DOES> part must do >instance as first thing
\ rewritten for OF816 by MAG
: (instance?) ( xt -- xt true|false )
dup 1+ @ dup ff and
22 = IF
8 rshift 3 na+ @ ['] >instance =
ELSE
drop false
THEN
;
\ This word does instance values in compile mode.
\ It corresponds to DOTO from engine.in
\ MAG: 1+ added because OF816 XTs and return addresses are one less...
: (doito) ( value R:*CFA -- )
r> cell+ dup >r 1+ ( MAG )
@ cell+ cell+ @ >instance !
;
' (doito) CONSTANT <(doito)>
\ Modified by MAG
: to ( value wordname<> -- )
' (instance?)
IF ( value xt )
state @ IF
['] (doito) , , \ compile mode handling instance value
ELSE
cell+ cell+ @ >instance ! \ interp mode instance value
THEN EXIT
ELSE
state @ IF ( value xt )
postpone literal compile (to)
ELSE
(to)
THEN
THEN
; IMMEDIATE
: behavior ( defer-xt -- contents-xt )
dup cell+ @ <instancedefer> = IF \ Is defer-xt an INSTANCE DEFER ?
2 cells + @ >instance @
ELSE
behavior
THEN
;
: INSTANCE ALSO instance-words ;
: my-parent my-self instance>parent @ ;
: my-args my-self instance>args 2@ swap ;
\ copy args from original instance to new created
: set-my-args ( old-addr len -- )
dup alloc-mem \ allocate space for new args ( old-addr len new-addr )
2dup my-self instance>args 2! \ write into instance struct ( old-addr len new-addr )
swap move \ and copy the args ( )
;
\ Current node has already been set, when this is called.
: create-instance-data ( -- instance )
get-node dup node>instance-template @ ( phandle instance-template )
swap node>instance-size @ ( instance-template instance-size )
dup >r
dup alloc-mem dup >r swap move r> ( instance )
dup instance>size r> swap ! \ Store size for destroy-instance
dup instance>#units 0 swap ! \ Use node unit by default
;
: create-instance ( -- )
my-self create-instance-data
dup to my-self instance>parent !
get-node my-self instance>node !
;
: destroy-instance ( instance -- )
dup instance>args @ ?dup IF \ Free instance args?
over instance>args-len @ free-mem
THEN
dup instance>size @ free-mem
;
: ihandle>phandle ( ihandle -- phandle )
dup 0= ABORT" no current instance" instance>node @
;
: push-my-self ( ihandle -- ) r> my-self >r >r to my-self ;
: pop-my-self ( -- ) r> r> to my-self >r ;
: call-package push-my-self execute pop-my-self ;
: $call-static ( ... str len node -- ??? )
\ cr ." call for " 3dup -rot type ." on node " .
find-method IF execute ELSE -1 throw THEN
;
: $call-my-method ( str len -- )
my-self ihandle>phandle $call-static
;
: $call-method ( str len ihandle -- )
push-my-self
['] $call-my-method CATCH ?dup IF
pop-my-self THROW
THEN
pop-my-self
;
0 VALUE calling-child
: $call-parent
my-self ihandle>phandle TO calling-child
my-parent $call-method
0 TO calling-child
;