Code Planting Tutorial Part 6 - GetPoplog/Seed GitHub Wiki
Work in progress ...
Implementing Pythonic Generators
Introduce this is a serious exercise, where we cover the bit about making it an autoloadable syntax in your personal library. A bit of chat about generators in Python. And then a bit of chat about coroutines in Poplog.
For this tutorial it helps to know:
- How to program with Poplog processes see REF PROCESS
- _Assigning to the discard (underscore) variable
_
will discard the value.
Problem
In this section we describe the extension to define and the yield keywords.
Strategy
Explain how we are going to do it. Especially about $poplib and autoloading.
Extending the define syntax
define lconstant read_revargs() -> revargs;
pop11_need_nextitem( "(" ) -> _;
lvars revargs = [];
until pop11_try_nextitem( ")" ) do
nextif( pop11_try_nextitem( "," ) );
lvars arg = readitem();
if arg.isword then
arg :: revargs -> revargs
else
mishap( 'Invalid parameter', [ ^arg ] )
endif
enduntil;
enddefine;
define :define_form generator;
lvars name = readitem();
lvars revargs = read_revargs();
sysSYNTAX( name, "procedure", pop_debugging == false );
sysPROCEDURE( name, revargs.length );
lvars a;
for a in revargs do
sysLVARS( a, 0 );
sysPOP( a );
endfor;
sysPUSH( "runproc" );
sysPUSH( "popstackmark" );
sysPUSHQ( 0 );
sysPUSHQ( 0 );
sysPROCEDURE( "generator_" <> name, 0 );
pop11_comp_stmnt_seq_to( "enddefine" ) -> _;
sysPUSHQ( termin );
sysPUSHQ( sysENDPROCEDURE() );
sysCALL( "consproc" );
sysCALL( "sysconslist" );
sysCALL( "partapply" );
sysPASSIGN( sysENDPROCEDURE(), name );
enddefine;
Implementing yield
define syntax yield;
dlocal pop_new_lvar_list;
pop11_need_nextitem( "(" ) -> _;
lvars tmpvar = sysNEW_LVAR();
sysCALL( "stacklength" );
sysPOP( tmpvar );
pop11_comp_expr_to( ")" ) -> _;
sysCALL( "stacklength" );
sysPUSH( tmpvar );
sysCALL( "fi_-" );
sysCALL( "suspend" );
enddefine;
define lconstant plant_yield_conditionally( if_unless );
pop11_need_nextitem( "(" ) -> _;
pop11_comp_expr_to( ")" ) -> _;
lvars sys_IF = if_unless and sysIFNOT else sysIFSO;
lvars skip_label = sysNEW_LABEL();
sysIFNOT( skip_label );
nonsyntax yield();
sysLABEL( skip_label );
enddefine;
define syntax yieldif;
plant_yield_conditionally( true )
enddefine;
define syntax yieldunless;
plant_yield_conditionally( false )
enddefine;