⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 script.c

📁 COP8 CPU的一个解释型BASIC源码
💻 C
字号:
////////////////////////////////////////////////////////////////
//
//                S C R I P T H E R M
//             A SCRIPTABLE THERMOMETER
// 
// entry of the National Semiconductor COP8FLASH Design Contest
//        submitted by Alberto Ricci Bitti (C) 2001
//              a.riccibitti@ra.nettuno.it
//
//--------------------------------------------------------------
//       FOR A BETTER VIEW SET TAB SIZE=4, INDENT SIZE=4
//--------------------------------------------------------------
// FILE   : script.c
// PURPOSE: the interpreter body, contains the routines
//          implementing the statements. 
//          Call the tokenizer to get a token, the executes it.
//          Implements the control stack for flow control
//          statements (IF-THEN-ELSE-ENDIF, WHILE-WEND)
//
////////////////////////////////////////////////////////////////

#include <stdlib.h>		
#include "types.h"
#include "ascii.h"
#include "memory.h"
#include "serial.h"
#include "lcd.h" //per cls
#include "errors.h"
#include "variables.h"
#include "language.h"
#include "tokenizer.h"
#include "expression.h"
#include "script.h"
#include "variables.h"
#include "main.h"

////////////////////////////////////////////////////////////////
// control stack
////////////////////////////////////////////////////////////////

ram_pointer_t prog = 0;

#define STACK_SIZE 10
ram_pointer_t control_stack[STACK_SIZE];
unsigned char tos = 0;


//pushes an address (usually the program counter) on the control stack
void push(ram_pointer_t pc)
{
	if (tos < STACK_SIZE) 		
	{
		control_stack[tos++]  = pc;
	}
	else						
		syntax_error(NESTING_TOO_DEEP);
}


ram_pointer_t pop(void)
{
	if (tos == 0)
		syntax_error(NESTING_UNBALANCED);
	return control_stack[--tos];
}

// skips a block of code, matching the give token
// e.g. WHILE skips to WEND, etc.
static void skip_block(unsigned char start_token)
{
	while(TRUE)
	{
		switch( get_token() )
		{
		case IF:
		case WHILE:
		case FUNCTION:
			skip_block( token ); 
			break;

		case END_WHILE:	
			ensure( start_token == WHILE, NESTING_UNBALANCED);
			return;
			
		case END_FUNCTION:	
			ensure( start_token == FUNCTION, NESTING_UNBALANCED);
			return;

		case END_IF: 
			ensure( start_token == IF || start_token == ELSE, NESTING_UNBALANCED);
			return;

		case END_FILE: 
			syntax_error(NESTING_UNBALANCED);
			/*break intentionally removed*/

		case END_PROGRAM:
			return;
			
		case ELSE:
			if ( start_token == ELSE ) return;
			break;
		};
	};
}



////////////////////////////////////////////////////////////////
// language statement routines
////////////////////////////////////////////////////////////////

//prints a number, called by PRINT
static void prettyprint(int n, void (*put_char)(unsigned char))			
{	
    unsigned char buf[5];
	signed char i;
	if (n < 0)  { n = -n;  	put_char('-');}
	else        { put_char(' '); };
    for (i=0; i<5; )	
    {			
    	buf[i++] = '0'+ n % 10;
    	n = n / 10;
    };
	do { i--; } while ( (buf[i] == '0') && (i != 0) );
	do { put_char( buf[i--] ); } while (i >= 0);
}



////////////////////////////////////////////////////////////////
//PRINT
////////////////////////////////////////////////////////////////
void print(void)
{   
    void (*put_char)(unsigned char) =  LCD_putchar;
	do
	{
		get_token();
		switch(token)
		{
		case AT:
			{ unsigned char r, c;
			r = get_expression();
			ensure(get_token() == COMMA ,  SYNTAX_ERROR); //expected:comma
			c = get_expression();
			LCD_locate(r,c);
			};
			break;

		case CR:
			put_char(END_OF_LINE);
			break;
		
		case COM:
			put_char = com_putchar;
			break;
		
		case QUOTE:
			while( peek_flash(++token_address) != APEX )
				put_char( peek_flash(token_address) );
			break;
		
		default:
			unget_token();
			prettyprint( get_expression(), put_char );
			break;
		};
	} while(get_token() == COMMA);
	unget_token();
}




////////////////////////////////////////////////////////////////
//GET
////////////////////////////////////////////////////////////////
void get_serial(void)
{
	ensure(get_token() == VARIABLE_NAME ,  SYNTAX_ERROR); //expected:variable
	set_variable( token_address, ( com_pending() ? com_getchar() : -1 ) );
}



////////////////////////////////////////////////////////////////
//BOX
////////////////////////////////////////////////////////////////
void box(void)
{   
    unsigned char x1,x2,y1,y2;
    unsigned char color = 1;
    unsigned char d;
	x1 = get_expression() & 0x7F;
	ensure(get_token() == COMMA ,  SYNTAX_ERROR); //expected:comma
	y1 = get_expression() & 0x3F;
	ensure(get_token() == COMMA ,  SYNTAX_ERROR); //expected:comma
	x2 = get_expression() & 0x7F;
	ensure(get_token() == COMMA ,  SYNTAX_ERROR); //expected:comma
	y2 = get_expression() & 0x3F;
	if (get_token() == COMMA)
	    color = get_expression();
	else
	    unget_token();
	if (x1 > x2)  { d = x2; x2 = x1; x1 = d; };
	if (y1 > y2)  { d = y2; y2 = y1; y1 = d; };
	for( ; y1 <= y2; y1++)
    	for ( d=x1; d <= x2; d++)
	       LCD_pset(d, y1, color); 
}


////////////////////////////////////////////////////////////////
// IF-THEN-ELSE-ENDIF
////////////////////////////////////////////////////////////////
void do_if(void)
{
	int condition;
	condition = get_expression();
	ensure (get_token() == THEN, EXPECTED_THEN);
	if(!condition)
	{
		skip_block(ELSE); //endif will do as well
	};
}

// ELSE
void do_else(void)
{
	skip_block(IF);
}



////////////////////////////////////////////////////////////////
// WHILE-WEND
////////////////////////////////////////////////////////////////
void do_while(void)
{
	push( token_address );

	if(!get_expression())
	{
		pop();
		skip_block(WHILE);
	}
}

// WEND
void end_while(void)
{
	prog = pop();
}



////////////////////////////////////////////////////////////////
// VAR
////////////////////////////////////////////////////////////////
void variable(void)
{
	do
	{
		if(	get_token() != VARIABLE_NAME ) syntax_error(EXPECTED_NAME);
		push_variable(token_address, 0);
	} while( get_token() == COMMA);
	unget_token();
}



////////////////////////////////////////////////////////////////
// FUNCTION
////////////////////////////////////////////////////////////////
void function(void)
{	
    ram_pointer_t function_name;
	unsigned char count=0;

	function_name = token_address;
	push_variable(RETURN_VALUE, 0);				//marks the frame and holds return value
	get_token();								//skip ( or ()
	do											
	{
		if ( token == PAR_CLOSE || token == PAR_VOID)	break;		
		push_variable( ANONIMUS, get_expression() );	//push parameters as anonimus variables
		count++;
	} while (get_token() == COMMA);	

	push(prog);									//push return address

	prog = (ram_pointer_t) get_variable( function_name );
												//jump to function body
	get_token();								//skip (
	do											
	{                                           //scan argument list
		if ( token == PAR_CLOSE || token == PAR_VOID)	break;		
		ensure(get_token() == VARIABLE_NAME, EXPECTED_NAME);
		name_parameter( token_address );		//rename anonymus parameters with argument names
		count--;
	} while (get_token() == COMMA);	
	ensure( count == 0, SYNTAX_ERROR);			//argument number mismatch
}


////////////////////////////////////////////////////////////////
// FUNCTION CALL - FEND
////////////////////////////////////////////////////////////////
void function_immediate(void)
{
	push(NULL_NAME);          //push NULL variable as return value recipient
	function();
}



////////////////////////////////////////////////////////////////
// FEND
////////////////////////////////////////////////////////////////
void end_function(void)
{
	prog = pop();			  //continue from where we left
	set_variable(pop(), pop_frame());
}



////////////////////////////////////////////////////////////////
// ASSIGNMENT (=)
////////////////////////////////////////////////////////////////
void assignment(void)
{		
	push( token_address );	                        //store name
	ensure( get_token() == ASSIGN, SYNTAX_ERROR);   //expected "="
	if (get_token() == FUNCTION_NAME) 
		//leave the variable name on top of stack, to be used by end_function
		function();
	else
	{
		unget_token();
		set_variable( pop(), get_expression() );
	};
}

// utilities
void end_program(void)
{	
	//an embedded program never ends really
	flags.running = FALSE;
	//restart editing from the beginning
	token_address = 0;
}

void do_nothing(void) 
{}



////////////////////////////////////////////////////////////////
//prepare the environment for program execution
////////////////////////////////////////////////////////////////

void prepare_to_run(void)
{
	flags.running = TRUE;
	tos = 0;
	reset_expression_evaluator();
	clear_variables();
	register_functions();
    token_address = prog = PROGRAM_START;
}



////////////////////////////////////////////////////////////////
// the real interpreter: gets a token and jump to the routine 
//                       that implements it
////////////////////////////////////////////////////////////////
void exec_command(void)
{	
	ensure(get_token() < MAX_RUNNABLE, SYNTAX_ERROR);
	jump_table[ token & 0x7F ]();
}


⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -