0){
$bcode = $codestack[$codep-1][0];
$searchpos = $codestack[$codep-1][1];
$mx = $codestack[$codep-1][2];
while($searchpos<$mx){
if(valtype($bcode[$searchpos])!=$type ||
valdata($bcode[$searchpos])!=$tag){
$searchpos++;
}
else{
return $searchpos;
}
}
$codep--;
}
return -1;
}
function run()
{
global $initialenv, $bcode, $bc, $errmsg;
global $envstack, $argstack, $envp, $argp;
global $stacktrace;
global $codestack, $codep;
$codestack = array(array($bcode, 0, $bc, -1, 0));
$codep = 1;
$argstack = array();
$argp = 0;
$b = 0;
while(1){
$instr = $codestack[$codep-1][0][$b];
// echo $b . ' ' . $instr[0] . "
\n";
if($stacktrace && $instr[0]!='start'){
echo "> ";
printargstack();
}
switch($instr[0]){
case 'cond':
$count = $instr[1];
$type = valdata($argstack[$argp-2]);
$code = valdata($argstack[$argp-1]);
if($type=='else'){
insertcode($b, $code, -1);
$b = -1;
unset($argstack[$argp-1]); $argp--;
unset($argstack[$argp-1]); $argp--;
}
else{
$tcode = valdata($argstack[$argp-3]);
insertcode($b, array(array('cond1', $count)), -1);
insertcode(-1, $tcode, -1);
$b = -1;
}
break;
case 'cond1':
$count = $instr[1];
$type = valdata($argstack[$argp-3]);
$code = valdata($argstack[$argp-2]);
$tres = $argstack[$argp-1];
if(!isfalse($tres)){
if($type=='proc'){
$pcode = array();
$pcode[] = array('checkptc', $tres);
$pcode[] = array('toargs', $tres);
$pcode[] = array('application', 1);
insertcode($b, $pcode, -1);
insertcode(-1, $code, -1);
}
else{
insertcode($b, $code, -1);
}
$b = -1;
$topop = $count+1;
}
else{
if($count>=3){
insertcode($b, array(array('cond', $count-3)), -1);
$b = -1;
}
$topop = 4;
}
for($c=0; $c<$topop; $c++){
unset($argstack[$argp-1]); $argp--;
}
break;
case 'case':
$count = $instr[1];
$caseval = $argstack[$argp-1-2*$count];
$casevaltype = valtype($caseval);
$casevaldata = valdata($caseval);
for($c=0; $c<$count; $c++){
$cases = $argstack[$argp-2];
$code = $argstack[$argp-1];
$match = 0;
if(valtype($cases)=='symbol'){
$match = 1;
}
else{
while(valtype($cases)=='pair'){
$item = car($cases);
if(valtype($item)==$casevaltype &&
valdata($item)==$casevaldata){
$match = 1;
break;
}
$cases = cdr($cases);
}
}
if($match){
insertcode($b, valdata($code), -1);
$b = -1;
break;
}
unset($argstack[$argp-1]); $argp--;
unset($argstack[$argp-1]); $argp--;
}
while($c<$count){
unset($argstack[$argp-1]); $argp--;
unset($argstack[$argp-1]); $argp--;
$c++;
}
unset($argstack[$argp-1]); $argp--;
break;
case 'thunk':
writeargptothunk($instr, -1);
break;
case 'argptothunk':
writeargptothunk($instr[1], $argp);
break;
case 'envptothunk':
writeenvptothunk($instr[1], $envp);
break;
case 'error':
$errmsg = $instr[1];
return -1;
case 'start':
$envstack = array($initialenv);
$envp = 1;
break;
case 'if':
if(isfalse($argstack[$argp-3])){
$icode = $argstack[$argp-1];
}
else{
$icode = $argstack[$argp-2];
}
insertcode($b, valdata($icode), -1);
$b = -1;
unset($argstack[$argp-1]);
unset($argstack[$argp-2]);
unset($argstack[$argp-3]);
$argp -= 3;
break;
case 'and':
case 'or':
$op = $instr[0];
$count = $instr[1];
if(valtype($argstack[$argp-1])!='boolean'){
$errmsg = 'boolean required in ' . $op .
'; got ' . valtype($argstack[$argp-1]);
return -1;
}
$bool = $argstack[$argp-1];
if(($op=='and' && valdata($bool)=='#t') ||
($op=='or' && valdata($bool)=='#f')){
if($count){
$tcode = valdata($argstack[$argp-2]);
insertcode($b, array(array($op, $count-1)), -1);
insertcode(-1, $tcode, -1);
$b = -1;
unset($argstack[$argp-1]); $argp--;
unset($argstack[$argp-1]); $argp--;
}
}
else{
unset($argstack[$argp-1]); $argp--; // boolean
while($count>0){
unset($argstack[$argp-1]); $argp--;
$count--;
}
$argstack[$argp++] = $bool;
}
break;
case 'closure':
$cl = newclosure($argstack[$argp-3],
$argstack[$argp-2],
$argstack[$argp-1],
$envstack[$envp-1]);
unset($argstack[$argp-1]);
unset($argstack[$argp-2]);
$argp -= 2;
$argstack[$argp-1] = $cl;
break;
case 'layer':
$newlayer = array();
for($p=$argp-2; $p>=$argp-2*$instr[1]; $p-=2){
$newlayer[$argstack[$p][1]] = $argstack[$p+1];
unset($argstack[$p]); unset($argstack[$p+1]);
}
$argp -= 2*$instr[1];
$envstack[$envp] = cons(newenv($newlayer), $envstack[$envp-1]);
$envp++;
break;
case 'listapplication':
$argl = $argstack[$argp-1];
if(valtype($argl)!='empty' &&
valtype($argl)!='pair'){
$errmsg = 'second arg to apply not a list';
return -1;
}
unset($argstack[--$argp]);
$argc = 0;
while(valtype($argl)=='pair'){
$argstack[$argp++] = car($argl);
$argc++;
$argl = cdr($argl);
}
// pass through to application
case 'application':
if($instr[0]=='application'){
$argc = $instr[1];
}
$op=$argstack[$argp-1-$argc];
if(valtype($op)=='primitive'){
$res = applyprimitive(valdata($op), $argc);
if(!is_array($res)){
return -1;
}
$newargp = $argp-$argc-1;
}
else if(valtype($op)=='thunk'){
if($argc!=1){
$errmsg = 'continuation requires a single argument';
return -1;
}
if(readargpfromthunk($op)==-1){
$errmsg = 'thunk #' . valdata($op) . ' has expired';
return -1;
}
$codestack[$codep-1][1] = $b;
$b = findmarkforward($op);
$newenvp = readenvpfromthunk($op);
while($envp>$newenvp){
unset($envstack[--$envp]);
}
$res = $argstack[$argp-1];
$newargp = readargpfromthunk($op);
}
else{
$newlayer = array();
$argl = closureargs($op);
if(valdata(closureargtype($op))>0){
for($p=$argp-$argc;
valtype($argl)=='pair'; $p++, $argl=cdr($argl)){
if($p>=$argp){
$errmsg = 'not enough arguments';
return -1;
}
$newlayer[valdata(car($argl))] = $argstack[$p];
}
if(valdata(closureargtype($op))==1){
$items = array();
while($p<$argp){
$items[] = $argstack[$p];
$p++;
}
$newlayer[valdata($argl)] = array2list($items);
}
else if($p<$argp){
$errmsg = 'too many arguments';
return -1;
}
}
else{
for($p=$argp-$argc, $items=array(); $p<$argp; $p++){
$items[] = $argstack[$p];
}
$newlayer[valdata($argl)] = array2list($items);
}
$tag = closuretag($op);
$tailrec = 0; $codestack[$codep-1][1] = $b;
$popcount = 0;
for($cp=$codep-1; $cp>=0; $cp--){
$pos = $codestack[$cp][1]+1;
$mx = $codestack[$cp][2];
while($pos<$mx){
$instr = $codestack[$cp][0][$pos];
if(valtype($instr)=='popenv'){
$popcount += valdata($instr);
$pos++;
}
else{
break;
}
}
if($pos<$mx){
break;
}
if($codestack[$cp][3]==$tag){
$tailrec = 1;
break;
}
}
if($tailrec){
$envp -= $popcount;
$envstack[$envp-1] =
cons(newenv($newlayer), closureenv($op));
$codep = $cp+1;
}
else{
$envstack[$envp] =
cons(newenv($newlayer), closureenv($op));
$envp++;
$lcode = valdata(closurebody($op));
insertcode($b, array(array('popenv', 1)), -1);
insertcode(-1, $lcode, $tag);
}
$b = -1;
$newargp = $argp-$argc-1;
}
while($argp>$newargp){
unset($argstack[--$argp]);
}
if(valtype($op)=='primitive' ||
valtype($op)=='thunk'){
$argstack[$argp] = $res;
$argp++;
}
break;
case 'toargs':
$argstack[$argp] = $instr[1];
$argp++;
break;
case 'popargs':
unset($argstack[$argp-1]);
$argp--;
break;
case 'popenv':
$count = $instr[1];
while($count>0){
unset($envstack[$envp-1]);
$envp--;
$count--;
}
break;
case 'globalenv':
$envstack[$envp] = $envstack[0];
$envp++;
break;
case 'checkptc':
$item = $argstack[$argp-1];
if(valtype($item)!='primitive' &&
valtype($item)!='closure' &&
valtype($item)!='thunk'){
$errmsg = 'primitive, closure or thunk required';
return -1;
}
break;
case 'lookup':
$item = $argstack[$argp-1];
$res = lookup(valdata($item), $envstack[$envp-1]);
if(!is_array($res)){
$errmsg = "symbol " . valdata($item) . " not bound";
return -1;
}
$argstack[$argp-1] = $res[1];
break;
case 'define':
case 'set!':
$val = $argstack[--$argp]; unset($argstack[$argp]);
$sym = $argstack[$argp-1];
$env = car($envstack[$envp-1]);
if($instr[0]=='set!'){
$res = lookup(valdata($sym), $envstack[$envp-1]);
if(is_array($res)){
$env = $res[0];
}
}
writetoenv($env, valdata($sym), $val);
break;
default:
$errmsg =
"instruction $instr[0] unknown " .
"(codestack: $codep, position: $b)
\n";
return -1;
}
$b++;
while($b==$codestack[$codep-1][2]){
$codep--;
if(!$codep){
break;
}
$b = $codestack[$codep-1][1]+1;
}
if(!$codep){
break;
}
}
return 0;
}
function compile($exp)
{
global $specialforms;
global $bcode, $bc;
if($exp[0]=='pair'){
$toapply = car($exp);
if($toapply[0]=='symbol'){
if(isset($specialforms[$toapply[1]])){
handlespecial($toapply[1], cdr($exp));
return;
}
}
for($item=$exp, $count=0; valtype($item)=='pair'; $item=cdr($item)){
$count++;
compile(car($item));
if($count==1){
$bcode[$bc++] = array('checkptc');
}
}
if(valtype($item)!='empty'){
$bcode[$bc++] = array('error', 'application not a proper list');
return;
}
$bcode[$bc++] = array('application', $count-1);
}
else if($exp[0]=='symbol'){
$bcode[$bc++] = array('toargs', $exp);
$bcode[$bc++] = array('lookup');
}
else{
$bcode[$bc++] = array('toargs', $exp);
}
}
?>
Scheme
Scheme
if(isset($program)){
if(!strcmp(strtoupper($showbytecodes), "ON")){
$showbytecodes=1; $sbc='CHECKED';
}
else{
$showbytecodes=0; $sbc='';
}
if(!strcmp(strtoupper($stacktrace), "ON")){
$stacktrace=1; $stacktr='CHECKED';
}
else{
$stacktrace=0; $stacktr='';
}
if(!strcmp(strtoupper($loadlibrary), "ON")){
$loadlibrary=1; $loadlib='CHECKED';
}
else{
$loadlibrary=0; $loadlib='';
}
init();
if($loadlibrary){
$stflag = $stacktrace; $stacktrace = 0;
$lname = "library.scm";
$fp = @fopen($lname, "r");
if($fp){
$library = fread($fp, filesize($lname));
fclose($fp);
tokenize($library);
$form = 1; $successes = 0;
while(isset($tokens[$base])){
$exp = readexp();
if(is_array($exp)){
$bcode = array(array('start')); $bc=1;
compile($exp);
$outputstr = '';
if(run()){
echo
"Library: form $form: " .
$errmsg .
"
\n";
}
else{
$successes++;
}
}
else{
echo
"Library: form $form: " .
$errmsg .
"
\n";
break;
}
$form++;
}
}
else{
echo
"" .
"Couldn't load library: $lname" .
"
\n";
}
if($successes){
echo
"" .
"Library: $lname: loaded $successes " .
"form" . ($succeses==1 ? '' : 's') . "." .
"
\n";
}
$stacktrace = $stflag;
}
$program = stripslashes($program);
tokenize($program);
$form = 1; $imageindex = 0;
while(isset($tokens[$base])){
$exp = readexp();
if(is_array($exp)){
echo "
Form $form
\n"; $form++;
$str = tohtmlstring2($exp);
echo "\n";
echo $str;
echo "
\n";
$bcode = array(array('start')); $bc=1;
compile($exp);
if($showbytecodes){
for($b=0; $b\n";
}
echo "
\n";
}
$imagedata = array(0, 0, 0, 0, array());
echo "";
$outputstr = '';
if(run()){
echo "" . $errmsg . "
\n";
}
printargstack();
echo "
\n";
if(strlen($outputstr)>0){
echo "Output\n";
echo
"
" .
htmlspecialchars($outputstr) .
"
\n";
}
echo "\n";
if(count($imagedata[4])>0){
$images[$imageindex] = $imagedata;
echo "
\n";
echo "\n";
echo " |
\n";
$imageindex++;
}
}
else{
echo "" . $errmsg . "
\n";
break;
}
}
}
?>
author(); ?>