A project to implement a console using the Mbed using VGA for video output and a PS/2 keyboard for the input. The eventual goal is to also include tools for managing SD cards, and a semi-self-hosting programming environment.

Dependencies:   PS2_MbedConsole fastlib SDFileSystem vga640x480g_mbedconsole lightvm mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers plEarlz.cpp Source File

plEarlz.cpp

00001 /*
00002 <Copyright Header>
00003 Copyright (c) 2012 Jordan "Earlz" Earls  <http://lastyearswishes.com>
00004 All rights reserved.
00005 
00006 Redistribution and use in source and binary forms, with or without
00007 modification, are permitted provided that the following conditions
00008 are met:
00009 
00010 1. Redistributions of source code must retain the above copyright
00011    notice, this list of conditions and the following disclaimer.
00012 2. Redistributions in binary form must reproduce the above copyright
00013    notice, this list of conditions and the following disclaimer in the
00014    documentation and/or other materials provided with the distribution.
00015 3. The name of the author may not be used to endorse or promote products
00016    derived from this software without specific prior written permission.
00017    
00018 THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
00019 INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
00020 AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
00021 THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00022 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00023 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
00024 OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
00025 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
00026 OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
00027 ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00028 
00029 This file is part of the MbedConsole project
00030 */
00031 
00032 #include "mbedconsole.h"
00033 #include "plEarlz.h"
00034 #include <stdarg.h>
00035 #include <stdint.h>
00036 //Basically a non-conforming take on Forth, btw.
00037 
00038 inline int internal_captureline(void* pBuffer, char const* pFormatString, ...)
00039 {
00040     char*   pStringEnd = (char*)pBuffer + strlen((char*)pBuffer);
00041     va_list valist;
00042     
00043     va_start(valist, pFormatString);
00044     
00045     return vsprintf(pStringEnd, pFormatString, valist);
00046 }
00047 void printheapstats()
00048 {
00049     char buffer[256];
00050     __heapstats(internal_captureline, buffer);
00051     vputs("Memory info: ");
00052     vputs(buffer);
00053 }
00054 
00055 
00056 
00057 
00058 
00059 BranchTarget *last_target=NULL;   
00060 
00061 ErrorType pl_error=None;
00062 
00063 
00064 enum WordType
00065 {
00066     Unknown,
00067     Number,
00068     Word,
00069     Quote
00070 };
00071 
00072 uint8_t *pl_codeblock;
00073 int pl_blockpos;
00074 int pl_blocksize;
00075 
00076 uint8_t* push_opcode_byte(uint8_t val)
00077 {
00078     if(pl_blockpos>=pl_blocksize)
00079     {
00080         void* tmp=realloc(pl_codeblock, pl_blocksize+CODEBLOCKSTEP);
00081         if(tmp==NULL)
00082         {
00083             vputs("Out of memory!!");
00084             return;
00085         }
00086         pl_codeblock=(uint8_t*)tmp;
00087         pl_blocksize+=CODEBLOCKSTEP;
00088     }
00089     pl_codeblock[pl_blockpos]=val;
00090     pl_blockpos++;
00091     return &pl_codeblock[pl_blockpos-1];
00092 }
00093 Opcode* push_opcode(Opcode val)
00094 {
00095     if(pl_blockpos>=pl_blocksize)
00096     {
00097         void* tmp=realloc(pl_codeblock, pl_blocksize+CODEBLOCKSTEP);
00098         if(tmp==NULL)
00099         {
00100             vputs("Out of memory!!");
00101             return;
00102         }
00103         pl_codeblock=(uint8_t*)tmp;
00104         pl_blocksize+=CODEBLOCKSTEP;
00105     }
00106     pl_codeblock[pl_blockpos]=(uint8_t)val;
00107     pl_blockpos++;
00108     return (Opcode*)&pl_codeblock[pl_blockpos-1];
00109 }
00110 uint16_t* push_opcode_word(uint16_t val)
00111 {
00112     if(pl_blockpos>=pl_blocksize)
00113     {
00114         void* tmp=realloc(pl_codeblock, pl_blocksize+CODEBLOCKSTEP);
00115         if(tmp==NULL)
00116         {
00117             vputs("Out of memory!!");
00118             return;
00119         }
00120         pl_codeblock=(uint8_t*)tmp;
00121         pl_blocksize+=CODEBLOCKSTEP;
00122     }
00123     *(uint16_t*)&pl_codeblock[pl_blockpos]=val;
00124     pl_blockpos+=2;
00125     return (uint16_t*)(&pl_codeblock[pl_blockpos-2]);
00126 }
00127 uint32_t* push_opcode_dword(uint32_t val)
00128 {
00129     if(pl_blockpos>=pl_blocksize)
00130     {
00131         void* tmp=realloc(pl_codeblock, pl_blocksize+CODEBLOCKSTEP);
00132         if(tmp==NULL)
00133         {
00134             vputs("Out of memory!!");
00135             return;
00136         }
00137         pl_codeblock=(uint8_t*)tmp;
00138         pl_blocksize+=CODEBLOCKSTEP;
00139     }
00140     *(uint32_t*)&pl_codeblock[pl_blockpos]=val;
00141     pl_blockpos+=4;
00142     return (uint32_t*)&pl_codeblock[pl_blockpos-4];
00143 }
00144 void new_codeblock(bool freeit)
00145 {
00146     if(freeit)
00147     {
00148         free(pl_codeblock);
00149     }
00150     pl_codeblock=(uint8_t*)malloc(CODEBLOCKSTEP);
00151     pl_blockpos=0;
00152     pl_blocksize=CODEBLOCKSTEP;
00153     last_target=NULL;
00154 }
00155 int execute_codeblock()
00156 {
00157     return forth_execute(pl_codeblock, pl_blockpos);
00158 }
00159  
00160 
00161 void push_target(int address)
00162 {
00163     BranchTarget* target=(BranchTarget*)malloc(sizeof(BranchTarget));
00164     target->previous=last_target;
00165     target->target=address;
00166     last_target=target;
00167 }
00168 void pop_target()
00169 {
00170     if(last_target==NULL)
00171     {
00172         vputs("Unmatched control statement!\n");
00173         return;
00174     }
00175     volatile void* tmp=last_target;
00176     last_target=last_target->previous;
00177     free((void*)tmp);
00178 }
00179 inline void write_blockword(int pos,uint16_t val)
00180 {
00181     *(uint16_t*)&pl_codeblock[pos]=val;
00182 }
00183 
00184 int compile_word(char *word, WordType type) //returns 0 for success, 1 for ending word found, -1 for error
00185 {
00186     if(type==Number){
00187         push_opcode(Push);
00188         push_opcode_dword(atoi(word));
00189     }else{
00190         if(word[1]==0) //check the quick builtins first
00191         {
00192             if(word[0]=='.'){
00193                 push_opcode(CallInt);
00194                 push_opcode_dword((uint32_t)&bi_print);
00195             }else if(word[0]==';')
00196             {
00197                 push_opcode(Ret);
00198                 //execute!
00199                 return 1;
00200             }else if(word[0]=='+'){
00201                 push_opcode(Add);
00202             }else if(word[0]=='/'){
00203                 push_opcode(Div);
00204             }else if(word[0]=='-'){
00205                 push_opcode(Sub);
00206             }else if(word[0]=='!'){
00207                 //pl_push(pl_pop()-pl_pop());
00208             }else if(word[0]=='%'){
00209                 push_opcode(Mod);
00210             }else if(word[0]=='*'){
00211                 push_opcode(Mul);
00212             }else if(word[0]=='!'){
00213                 //push_opcode(Store);
00214             }else if(word[0]=='?'){
00215                 pl_push(*(int*)pl_pop());
00216             }else if(word[0]=='='){
00217                 pl_push(pl_pop() == pl_pop());
00218             }else if(word[0]=='`'){
00219                 pl_push(pl_pop()>0);
00220             }else if(word[0]=='$'){
00221                 //print string (address on stack
00222             }else if(word[0]=='['){
00223                 //begin quotation
00224                 push_opcode(Push);
00225                 push_opcode_word(pl_blockpos+3);
00226                 push_opcode(Branch);
00227                 push_target(pl_blockpos);
00228                 push_opcode_word(0);
00229             }else if(word[0] == ']'){
00230                 //end quotation
00231                 push_opcode(Ret);
00232                 write_blockword(last_target->target, pl_blockpos);
00233                 pop_target();
00234             }
00235         }else if(strlcmp("if", word, 3)==0){
00236             push_opcode(BranchFalse);
00237             push_target(pl_blockpos);
00238             push_opcode_word(0);
00239         }else if(strlcmp("else", word, 5)==0){
00240             push_opcode(Branch);
00241             int tmp=pl_blockpos;
00242             push_opcode_word(0); 
00243             write_blockword(last_target->target,pl_blockpos);
00244             pop_target(); 
00245             push_target(tmp); //have to do it after we pop it or we fall into an infinite loop!
00246         }else if(strlcmp("end", word, 4)==0){
00247             write_blockword(last_target->target,(uint16_t)pl_blockpos);
00248             pop_target();
00249         }else if(strlcmp("tif", word, 4)==0){
00250             /**
00251             swap value 2 behind stack to front
00252             call.true 1 from stack
00253             call.false top of stack
00254             _label:
00255             **/
00256             //alloca(10);
00257             push_opcode(Push);
00258             push_opcode_dword(3);
00259             push_opcode(Pick);
00260             push_opcode(BranchFalse);
00261             //push_opcode_word(pl_blockpos+
00262             
00263         }else{
00264             vputs("I don't know the word '");
00265             vputs(word);
00266             vputs("'\n");
00267         }
00268     }
00269     return 0;
00270 }
00271 
00272 
00273 
00274 void parse_line(char *line)
00275 {
00276     int len=strlen(line);
00277     char word[16];
00278     word[0]=0;
00279     int wordpos=0;
00280     WordType type=Unknown;
00281     for(int i=0;i<len;i++)
00282     {
00283         char c=line[i];
00284         if(is_whitespace(c) || c=='\\')
00285         {
00286             if(word[0]!=0)
00287             {
00288                 word[wordpos]=0;
00289                 
00290                 int tmp=compile_word(word,type);
00291                 if(tmp==1)
00292                 {
00293                     execute_codeblock();
00294                     new_codeblock(true);
00295                 }
00296                 word[0]=0;
00297             }
00298             wordpos=0;
00299             type=Unknown;
00300             if(c=='\\'){
00301                 return; //rest is a comment
00302             }
00303         }else if(is_numeric(c)){
00304             if(type==Unknown){
00305                 type=Number;
00306             }
00307             word[wordpos]=c;
00308             wordpos++;
00309         }else if(is_quote(c)){
00310             push_opcode(LoadStr);
00311             for(;i<len;i++)
00312             {
00313                 //char c=line[
00314             }
00315             vputs("This isn't supported yet foo!");
00316             return;
00317         }else{
00318             if(type==Number){
00319                 vputs("Syntax Error! Unexpected symbol in the middle of a number");
00320                 return;
00321             }
00322             type=Word;
00323             word[wordpos]=c;
00324             wordpos++;
00325         }
00326     }
00327 }
00328 
00329 
00330 void tester()
00331 {
00332     printf("foo!");
00333 }
00334 
00335 int pl_shell()
00336 {
00337     vputs(">>plEarlz -- A forth-ish shell<<\n");
00338     printheapstats();
00339     vputs("\n");
00340     char *line=(char*)malloc(MAXLINELENGTH);
00341     sprintf(line, "Stack Size: %i; Max Recursion Level %i; Loaded WORDs: %i", MAXSTACK, MAXTEMPSTACK, 0);
00342     vputs(line);
00343     sprintf(line, "Max line length: %i\n", MAXLINELENGTH);
00344     vputs(line);
00345     new_codeblock(false);
00346     char *tmp=(char*)malloc(32); //for constructing words/elements
00347     while(1)
00348     {
00349         vputs("cmd> ");
00350         vgetsl(line, MAXLINELENGTH);
00351         line[MAXLINELENGTH-1]=0;
00352         int len=strlen(line);
00353         line[len]='\n';
00354         line[len+1]=0;
00355         parse_line(line);
00356     
00357     }
00358     free(line);
00359     free(tmp);
00360     return 0;
00361 }
00362 
00363