From: John Hodge Date: Tue, 24 Apr 2012 07:06:23 +0000 (+0800) Subject: Merge branch 'master' of git.mutabah.net:acess2 X-Git-Tag: rel0.15~711^2 X-Git-Url: https://git.ucc.asn.au/?a=commitdiff_plain;h=4538ee944b71b52f183809978cccfe60143d70c5;hp=16a3122b498e81b7aa515a4f21c03aff8e790e50;p=tpg%2Facess2.git Merge branch 'master' of git.mutabah.net:acess2 --- diff --git a/BuildConf/x86/default.mk b/BuildConf/x86/default.mk index 592d7020..a4ce8942 100644 --- a/BuildConf/x86/default.mk +++ b/BuildConf/x86/default.mk @@ -3,7 +3,7 @@ MODULES += Storage/ATA MODULES += Storage/FDDv2 MODULES += Network/NE2000 Network/RTL8139 MODULES += Display/VESA -MODULES += Display/BochsGA +MODULES += Display/BochsGA Display/VIAVideo MODULES += Input/PS2KbMouse MODULES += x86/ISADMA x86/VGAText diff --git a/KernelLand/Kernel/arch/armv7/proc.S b/KernelLand/Kernel/arch/armv7/proc.S index 8711dee6..19790583 100644 --- a/KernelLand/Kernel/arch/armv7/proc.S +++ b/KernelLand/Kernel/arch/armv7/proc.S @@ -49,9 +49,8 @@ SwitchTask: # mov r1, #1 mcrne p15, 0, r1, c8, c7, 0 @ TLBIALL - Invalid user space - @ Restore SP + @ Restore state mov sp, r0 - bx r2 .return: @@ -102,3 +101,5 @@ csProc_CloneInt_NewTaskMessage: .asciz "New task PC=%p, R4=%p, sp=%p" csProc_CloneInt_OldTaskMessage: .asciz "Parent task PC=%p, R4=%p, SP=%p" + +@ vim: ft=armv7 diff --git a/KernelLand/Kernel/arch/x86/irq.c b/KernelLand/Kernel/arch/x86/irq.c index e2dcf0e3..3d23636e 100644 --- a/KernelLand/Kernel/arch/x86/irq.c +++ b/KernelLand/Kernel/arch/x86/irq.c @@ -26,6 +26,7 @@ void *gaIRQ_DataPointers[16][MAX_CALLBACKS_PER_IRQ]; void IRQ_Handler(tRegs *Regs) { int i, irq = Regs->int_num - 0xF0; + int bHandled = 0; //Log("IRQ_Handler: (Regs={int_num:%i})", Regs->int_num); @@ -37,8 +38,13 @@ void IRQ_Handler(tRegs *Regs) if( irq != 8 ) Log("IRQ %i: Call %p", Regs->int_num, gIRQ_Handlers[Regs->int_num][i]); #endif + bHandled = 1; } } + + if( !bHandled ) { + Log_Debug("IRQ", "Unhandled IRQ %i", irq); + } //Log(" IRQ_Handler: Resetting"); if(irq >= 8) diff --git a/KernelLand/Kernel/arch/x86/vm8086.c b/KernelLand/Kernel/arch/x86/vm8086.c index d93bdf18..44c60dff 100644 --- a/KernelLand/Kernel/arch/x86/vm8086.c +++ b/KernelLand/Kernel/arch/x86/vm8086.c @@ -10,6 +10,8 @@ #include // === CONSTANTS === +#define TRACE_EMU 0 + #define VM8086_MAGIC_CS 0xFFFF #define VM8086_MAGIC_IP 0x0010 #define VM8086_STACK_SEG 0x9F00 @@ -54,6 +56,7 @@ tPID gVM8086_WorkerPID; tTID gVM8086_CallingThread; tVM8086 volatile * volatile gpVM8086_State = (void*)-1; // Set to -1 to avoid race conditions Uint32 gaVM8086_MemBitmap[VM8086_BLOCKCOUNT/32]; + int gbVM8086_ShadowIF = 0; // === FUNCTIONS === int VM8086_Install(char **Arguments) @@ -91,11 +94,11 @@ int VM8086_Install(char **Arguments) MM_Map( 0, 0 ); // IVT / BDA // Map (but allow allocation) of 0x1000 - 0x9F000 // - So much hack, it isn't funny + // TODO: Remove this and replce with something less hacky for(i=1;i<0x9F;i++) { MM_Map( i * 0x1000, i * 0x1000 ); - MM_DerefPhys( i * 0x1000 ); // Above while(MM_GetRefCount(i*0x1000)) - MM_DerefPhys( i * 0x1000 ); // Phys setup + MM_DerefPhys( i * 0x1000 ); } MM_Map( 0x9F000, 0x9F000 ); // Stack / EBDA // System Stack / Stub @@ -165,9 +168,12 @@ int VM8086_Install(char **Arguments) void VM8086_GPF(tRegs *Regs) { Uint8 opcode; + Uint16 newcs, newip; // Log_Log("VM8086", "GPF - %04x:%04x", Regs->cs, Regs->eip); - + + LOG("VM8086 GPF at %04x:%04x", Regs->cs, Regs->eip); + if(Regs->eip == VM8086_MAGIC_IP && Regs->cs == VM8086_MAGIC_CS && Threads_GetPID() == gVM8086_WorkerPID) { @@ -219,17 +225,24 @@ void VM8086_GPF(tRegs *Regs) case VM8086_OP_PUSHF: //PUSHF Regs->esp -= 2; *(Uint16*)( Regs->ss*16 + (Regs->esp&0xFFFF) ) = Regs->eflags & 0xFFFF; + if( gbVM8086_ShadowIF ) + *(Uint16*)( Regs->ss*16 + (Regs->esp&0xFFFF) ) |= 0x200; + else + *(Uint16*)( Regs->ss*16 + (Regs->esp&0xFFFF) ) &= ~0x200; #if TRACE_EMU - Log_Debug("VM8086", "Emulated PUSHF"); + Log_Debug("VM8086", "%04x:%04x Emulated PUSHF (value 0x%x)", + Regs->cs, Regs->eip-1, Regs->eflags & 0xFFFF); #endif break; case VM8086_OP_POPF: //POPF // Changing IF is not allowed Regs->eflags &= 0xFFFF0202; Regs->eflags |= *(Uint16*)( Regs->ss*16 + (Regs->esp&0xFFFF) ); + gbVM8086_ShadowIF = !!(*(Uint16*)( Regs->ss*16 + (Regs->esp&0xFFFF) ) & 0x200); Regs->esp += 2; #if TRACE_EMU - Log_Debug("VM8086", "Emulated POPF"); + Log_Debug("VM8086", "%04x:%04x Emulated POPF (new value 0x%x)", + Regs->cs, Regs->eip-1, Regs->eflags & 0xFFFF); #endif break; @@ -242,20 +255,26 @@ void VM8086_GPF(tRegs *Regs) Regs->esp -= 2; *(Uint16*)( Regs->ss*16 + (Regs->esp&0xFFFF) ) = Regs->cs; Regs->esp -= 2; *(Uint16*)( Regs->ss*16 + (Regs->esp&0xFFFF) ) = Regs->eip; - Regs->cs = *(Uint16*)(4*id + 2); - Regs->eip = *(Uint16*)(4*id); + newcs = *(Uint16*)(4*id + 2); + newip = *(Uint16*)(4*id); #if TRACE_EMU - Log_Debug("VM8086", "Emulated INT 0x%x", id); + Log_Debug("VM8086", "%04x:%04x Emulated INT 0x%x (%04x:%04x) - AX=%04x,BX=%04x", + Regs->cs, Regs->eip-2, id, newcs, newip, Regs->eax, Regs->ebx); #endif + Regs->cs = newcs; + Regs->eip = newip; } break; case VM8086_OP_IRET: //IRET - Regs->eip = *(Uint16*)( Regs->ss*16 + (Regs->esp&0xFFFF) ); Regs->esp += 2; - Regs->cs = *(Uint16*)( Regs->ss*16 + (Regs->esp&0xFFFF) ); Regs->esp += 2; + newip = *(Uint16*)( Regs->ss*16 + (Regs->esp&0xFFFF) ); Regs->esp += 2; + newcs = *(Uint16*)( Regs->ss*16 + (Regs->esp&0xFFFF) ); Regs->esp += 2; #if TRACE_EMU - Log_Debug("VM8086", "IRET to %04x:%04x", Regs->cs, Regs->eip); + Log_Debug("VM8086", "%04x:%04x IRET to %04x:%04x", + Regs->cs, Regs->eip-1, newcs, newip); #endif + Regs->cs = newcs; + Regs->eip = newip; break; @@ -263,55 +282,72 @@ void VM8086_GPF(tRegs *Regs) Regs->eax &= 0xFFFFFF00; Regs->eax |= inb(Regs->edx&0xFFFF); #if TRACE_EMU - Log_Debug("VM8086", "Emulated IN AL, DX (Port 0x%x)\n", Regs->edx&0xFFFF); + Log_Debug("VM8086", "%04x:%04x Emulated IN AL, DX (Port 0x%x [Val 0x%02x])", + Regs->cs, Regs->eip-1, Regs->edx&0xFFFF, Regs->eax&0xFF); #endif break; case VM8086_OP_IN_ADX: //IN AX, DX Regs->eax &= 0xFFFF0000; Regs->eax |= inw(Regs->edx&0xFFFF); #if TRACE_EMU - Log_Debug("VM8086", "Emulated IN AX, DX (Port 0x%x)\n", Regs->edx&0xFFFF); + Log_Debug("VM8086", "%04x:%04x Emulated IN AX, DX (Port 0x%x [Val 0x%04x])", + Regs->cs, Regs->eip-1, Regs->edx&0xFFFF, Regs->eax&0xFFFF); #endif break; case VM8086_OP_OUT_AD: //OUT DX, AL outb(Regs->edx&0xFFFF, Regs->eax&0xFF); #if TRACE_EMU - Log_Debug("VM8086", "Emulated OUT DX, AL (*0x%04x = 0x%02x)\n", Regs->edx&0xFFFF, Regs->eax&0xFF); + Log_Debug("VM8086", "%04x:%04x Emulated OUT DX, AL (*0x%04x = 0x%02x)", + Regs->cs, Regs->eip-1, Regs->edx&0xFFFF, Regs->eax&0xFF); #endif break; case VM8086_OP_OUT_ADX: //OUT DX, AX outw(Regs->edx&0xFFFF, Regs->eax&0xFFFF); #if TRACE_EMU - Log_Debug("VM8086", "Emulated OUT DX, AX (*0x%04x = 0x%04x)\n", Regs->edx&0xFFFF, Regs->eax&0xFFFF); + Log_Debug("VM8086", "%04x:%04x Emulated OUT DX, AX (*0x%04x = 0x%04x)", + Regs->cs, Regs->eip-1, Regs->edx&0xFFFF, Regs->eax&0xFFFF); #endif break; // TODO: Decide on allowing VM8086 Apps to enable/disable interrupts case 0xFA: //CLI + #if TRACE_EMU + Log_Debug("VM8086", "%04x:%04x Ignored CLI", + Regs->cs, Regs->eip); + #endif + gbVM8086_ShadowIF = 0; break; case 0xFB: //STI + #if TRACE_EMU + Log_Debug("VM8086", "%04x:%04x Ignored STI", + Regs->cs, Regs->eip); + #endif + gbVM8086_ShadowIF = 1; break; case 0x66: opcode = *(Uint8*)( (Regs->cs*16) + (Regs->eip&0xFFFF)); + Regs->eip ++; switch( opcode ) { case VM8086_OP_IN_ADX: //IN AX, DX Regs->eax = ind(Regs->edx&0xFFFF); #if TRACE_EMU - Log_Debug("VM8086", "Emulated IN EAX, DX (Port 0x%x)\n", Regs->edx&0xFFFF); + Log_Debug("VM8086", "%04x:%04x Emulated IN EAX, DX (Port 0x%x [Val 0x%08x])", + Regs->cs, Regs->eip-1, Regs->edx&0xFFFF, Regs->eax); #endif break; case VM8086_OP_OUT_ADX: //OUT DX, AX outd(Regs->edx&0xFFFF, Regs->eax); #if TRACE_EMU - Log_Debug("VM8086", "Emulated OUT DX, EAX (*0x%04x = 0x%08x)\n", Regs->edx&0xFFFF, Regs->eax); + Log_Debug("VM8086", "%04x:%04x Emulated OUT DX, EAX (*0x%04x = 0x%08x)", + Regs->cs, Regs->eip-1, Regs->edx&0xFFFF, Regs->eax); #endif break; default: Log_Error("VM8086", "Error - Unknown opcode 66 %02x caused a GPF at %04x:%04x", - Regs->cs, Regs->eip, + Regs->cs, Regs->eip-2, opcode ); // Force an end to the call @@ -332,7 +368,7 @@ void VM8086_GPF(tRegs *Regs) default: Log_Error("VM8086", "Error - Unknown opcode %02x caused a GPF at %04x:%04x", - opcode, Regs->cs, Regs->eip); + opcode, Regs->cs, Regs->eip-1); // Force an end to the call Regs->cs = VM8086_MAGIC_CS; Regs->eip = VM8086_MAGIC_IP; diff --git a/KernelLand/Kernel/debug.c b/KernelLand/Kernel/debug.c index 9edf1264..6a50ca2c 100644 --- a/KernelLand/Kernel/debug.c +++ b/KernelLand/Kernel/debug.c @@ -1,17 +1,13 @@ /* * AcessOS Microkernel Version * debug.c - * - * TODO: Move the Debug_putchar methods out to the arch/ tree */ #include #include #define DEBUG_MAX_LINE_LEN 256 - -#define LOCK_DEBUG_OUTPUT 1 - -#define TRACE_TO_KTERM 1 +#define LOCK_DEBUG_OUTPUT 1 // Avoid interleaving of output lines? +#define TRACE_TO_KTERM 0 // Send ENTER/DEBUG/LEAVE to debug? // === IMPORTS === extern void Threads_Dump(void); diff --git a/KernelLand/Kernel/drv/vterm.c b/KernelLand/Kernel/drv/vterm.c index 5f4a25ca..1cc60bec 100644 --- a/KernelLand/Kernel/drv/vterm.c +++ b/KernelLand/Kernel/drv/vterm.c @@ -758,6 +758,8 @@ void VT_SetTerminal(int ID) giVT_CurrentTerminal = ID; gpVT_CurTerm = &gVT_Terminals[ID]; + LOG("Attempting VT_SetMode"); + if( gpVT_CurTerm->Mode == TERM_MODE_TEXT ) { VT_SetMode( VIDEO_BUFFMT_TEXT ); @@ -769,7 +771,9 @@ void VT_SetTerminal(int ID) VFS_IOCtl(giVT_OutputDevHandle, VIDEO_IOCTL_SETCURSORBITMAP, gpVT_CurTerm->VideoCursor); VT_SetMode( VIDEO_BUFFMT_FRAMEBUFFER ); } - + + LOG("Mode set"); + if(gpVT_CurTerm->Buffer) { // TODO: Handle non equal sized @@ -779,9 +783,11 @@ void VT_SetTerminal(int ID) gpVT_CurTerm->Width*gpVT_CurTerm->Height*sizeof(Uint32), gpVT_CurTerm->Buffer ); + LOG("Updated screen contents"); } VT_int_UpdateCursor(gpVT_CurTerm, 1); // Update the screen VT_int_UpdateScreen(gpVT_CurTerm, 1); + LOG("done"); } diff --git a/KernelLand/Kernel/drv/vterm_output.c b/KernelLand/Kernel/drv/vterm_output.c index 4d1c352b..357132c0 100644 --- a/KernelLand/Kernel/drv/vterm_output.c +++ b/KernelLand/Kernel/drv/vterm_output.c @@ -7,7 +7,7 @@ */ #include "vterm.h" #include -#define DEBUG 1 +#define DEBUG 0 // === CODE === /** diff --git a/KernelLand/Kernel/drvutil.c b/KernelLand/Kernel/drvutil.c index d9bd92df..d2c86bfb 100644 --- a/KernelLand/Kernel/drvutil.c +++ b/KernelLand/Kernel/drvutil.c @@ -136,7 +136,7 @@ int DrvUtil_Video_WriteLFB(tDrvUtil_Video_BufInfo *FBInfo, size_t Offset, size_t int x, y; int bytes_per_px = (FBInfo->Depth + 7) / 8; ENTER("pFBInfo xOffset xLength pBuffer", - Mode, FBInfo, Offset, Length, Buffer); + FBInfo, Offset, Length, Buffer); csr_x = FBInfo->CursorX; csr_y = FBInfo->CursorY; @@ -287,9 +287,12 @@ int DrvUtil_Video_SetCursor(tDrvUtil_Video_BufInfo *Buf, tVideo_IOCtl_Bitmap *Bi int csrX = Buf->CursorX, csrY = Buf->CursorY; size_t size; + ENTER("pBuf pBitmap", Buf, Bitmap); + // Clear old bitmap if( Buf->CursorBitmap ) { + LOG("Clearing old cursor"); DrvUtil_Video_RemoveCursor(Buf); if( !Bitmap || Bitmap->W != Buf->CursorBitmap->W || Bitmap->H != Buf->CursorBitmap->H ) { @@ -306,24 +309,29 @@ int DrvUtil_Video_SetCursor(tDrvUtil_Video_BufInfo *Buf, tVideo_IOCtl_Bitmap *Bi { Buf->CursorX = -1; Buf->CursorY = -1; + LEAVE('i', 0); return 0; } // Sanity check the bitmap + LOG("Sanity checking plox"); if( !CheckMem(Bitmap, sizeof(*Bitmap)) || !CheckMem(Bitmap->Data, Bitmap->W*Bitmap->H*sizeof(Uint32)) ) { Log_Warning("DrvUtil", "DrvUtil_Video_SetCursor: Bitmap (%p) is in invalid memory", Bitmap); errno = -EINVAL; + LEAVE('i', -1); return -1; } // Don't take a copy of the DrvUtil provided cursor if( Bitmap == &gDrvUtil_TextModeCursor ) { + LOG("No copy (provided cursor)"); Buf->CursorBitmap = Bitmap; } else { + LOG("Make copy"); size = sizeof(tVideo_IOCtl_Bitmap) + Bitmap->W*Bitmap->H*4; // Take a copy @@ -332,7 +340,9 @@ int DrvUtil_Video_SetCursor(tDrvUtil_Video_BufInfo *Buf, tVideo_IOCtl_Bitmap *Bi } // Restore cursor position + LOG("Drawing"); DrvUtil_Video_DrawCursor(Buf, csrX, csrY); + LEAVE('i', 0); return 0; } @@ -340,24 +350,30 @@ void DrvUtil_Video_DrawCursor(tDrvUtil_Video_BufInfo *Buf, int X, int Y) { int render_ox=0, render_oy=0, render_w, render_h; + ENTER("pBuf iX iY", Buf, X, Y); DrvUtil_Video_RemoveCursor(Buf); // X < 0 disables the cursor if( X < 0 ) { Buf->CursorX = -1; + LEAVE('-'); return ; } // Sanity checking - if( X < 0 || Y < 0 ) return; - if( X >= Buf->Width || Y >= Buf->Height ) return; + if( X < 0 || Y < 0 || X >= Buf->Width || Y >= Buf->Height ) { + LEAVE('-'); + return ; + } // Ensure the cursor is enabled - if( !Buf->CursorBitmap ) return ; + if( !Buf->CursorBitmap ) { + LEAVE('-'); + return ; + } // Save cursor position (for changing the bitmap) Buf->CursorX = X; Buf->CursorY = Y; - // Apply cursor's center offset X -= Buf->CursorBitmap->XOfs; Y -= Buf->CursorBitmap->YOfs; @@ -375,8 +391,12 @@ void DrvUtil_Video_DrawCursor(tDrvUtil_Video_BufInfo *Buf, int X, int Y) Buf->CursorDestX = X; Buf->CursorDestY = Y; Buf->CursorReadX = render_ox; Buf->CursorReadY = render_oy; + LOG("%ix%i at %i,%i offset %i,%i", + render_w, render_h, X, Y, render_ox, render_oy); + // Call render routine DrvUtil_Video_RenderCursor(Buf); + LEAVE('-'); } void DrvUtil_Video_RenderCursor(tDrvUtil_Video_BufInfo *Buf) @@ -393,10 +413,13 @@ void DrvUtil_Video_RenderCursor(tDrvUtil_Video_BufInfo *Buf) dest = (Uint8*)Buf->Framebuffer + dest_y*Buf->Pitch + dest_x*bytes_per_px; src = Buf->CursorBitmap->Data + src_y * Buf->CursorBitmap->W + src_x; + LOG("dest = %p, src = %p", dest, src); + // Allocate save buffer if not already if( !Buf->CursorSaveBuf ) Buf->CursorSaveBuf = malloc( Buf->CursorBitmap->W*Buf->CursorBitmap->H*bytes_per_px ); + LOG("Saving back"); // Save behind the cursor for( y = 0; y < render_h; y ++ ) memcpy( @@ -413,6 +436,7 @@ void DrvUtil_Video_RenderCursor(tDrvUtil_Video_BufInfo *Buf) Log_Warning("DrvUtil", "TODO: Support 15/16 bpp modes in cursor draw"); break; case 24: + LOG("24-bit render"); for( y = 0; y < render_h; y ++ ) { Uint8 *px; @@ -435,6 +459,7 @@ void DrvUtil_Video_RenderCursor(tDrvUtil_Video_BufInfo *Buf) } break; case 32: + LOG("32-bit render"); for( y = 0; y < render_h; y ++ ) { Uint32 *px; @@ -448,6 +473,7 @@ void DrvUtil_Video_RenderCursor(tDrvUtil_Video_BufInfo *Buf) else ; // NOP, completely transparent } + LOG("row %i/%i (%p-%P) done", y+1, render_h, dest, MM_GetPhysAddr(dest)); src += Buf->CursorBitmap->W; dest = (Uint8*)dest + Buf->Pitch; } diff --git a/KernelLand/Modules/Display/VESA/common.h b/KernelLand/Modules/Display/VESA/common.h index eeaddd56..c81fe1a8 100644 --- a/KernelLand/Modules/Display/VESA/common.h +++ b/KernelLand/Modules/Display/VESA/common.h @@ -22,7 +22,24 @@ typedef struct sVesa_Mode typedef struct sVesa_CallModeInfo { + /** + * 0 : Mode is supported + * 1 : Optional information avaliable (Xres onwards) + * 2 : BIOS Output Supported + * 3 : Colour Mode? + * 4 : Graphics mode? + * -- VBE v2.0+ + * 5 : Mode is not VGA compatible + * 6 : Bank switched mode supported + * 7 : Linear framebuffer mode supported + * 8 : Double-scan mode avaliable + */ Uint16 attributes; + /** + * 0 : Window exists + * 1 : Window is readable + * 2 : Window is writable + */ Uint8 winA,winB; Uint16 granularity; Uint16 winsize; @@ -35,25 +52,32 @@ typedef struct sVesa_CallModeInfo Uint8 memory_model, bank_size, image_pages; Uint8 reserved0; + // -- VBE v1.2+ Uint8 red_mask, red_position; Uint8 green_mask, green_position; Uint8 blue_mask, blue_position; Uint8 rsv_mask, rsv_position; Uint8 directcolor_attributes; - Uint32 physbase; // Your LFB address ;) - Uint32 reserved1; - Sint16 reserved2; + // -- VBE v2.0+ + Uint32 physbase; + Uint32 offscreen_ptr; // Start of offscreen memory + Uint16 offscreen_size_kb; // Size of offscreen memory + + // -- VBE v3.0 + Uint16 lfb_pitch; + Uint8 image_count_banked; + Uint8 image_count_lfb; } tVesa_CallModeInfo; typedef struct sVesa_CallInfo { - char signature[4]; // == "VESA" - Uint16 Version; // == 0x0300 for Vesa 3.0 - tFarPtr OEMString; // isa vbeFarPtr - Uint8 Capabilities[4]; - tFarPtr VideoModes; // isa vbeParPtr - Uint16 TotalMemory; // as # of 64KB blocks + char signature[4]; // == "VESA" + Uint16 Version; // == 0x0300 for Vesa 3.0 + tFarPtr OEMString; // isa vbeFarPtr + Uint8 Capabilities[4]; + tFarPtr VideoModes; // isa vbeParPtr + Uint16 TotalMemory; // as # of 64KB blocks } tVesa_CallInfo; #endif diff --git a/KernelLand/Modules/Display/VESA/main.c b/KernelLand/Modules/Display/VESA/main.c index 2dbc98ce..ddf0671a 100644 --- a/KernelLand/Modules/Display/VESA/main.c +++ b/KernelLand/Modules/Display/VESA/main.c @@ -16,6 +16,8 @@ // === CONSTANTS === #define FLAG_LFB 0x1 +#define FLAG_POPULATED 0x2 +#define FLAG_VALID 0x4 #define VESA_DEFAULT_FRAMEBUFFER (KERNEL_BASE|0xA0000) #define BLINKING_CURSOR 1 #if BLINKING_CURSOR @@ -24,6 +26,7 @@ // === PROTOTYPES === int Vesa_Install(char **Arguments); + int VBE_int_GetModeList(void); size_t Vesa_Write(tVFS_Node *Node, off_t Offset, size_t Length, const void *Buffer); int Vesa_IOCtl(tVFS_Node *Node, int ID, void *Data); int Vesa_Int_SetMode(int Mode); @@ -67,6 +70,27 @@ tDrvUtil_Video_BufInfo gVesa_BufInfo; // === CODE === int Vesa_Install(char **Arguments) +{ + int rv; + + gpVesa_BiosState = VM8086_Init(); + + if( (rv = VBE_int_GetModeList()) ) + return rv; + + #if BLINKING_CURSOR + // Create blink timer + gpVesaCursorTimer = Time_AllocateTimer( Vesa_FlipCursor, NULL ); + #endif + + // Install Device + giVesaDriverId = DevFS_AddDevice( &gVesa_DriverStruct ); + if(giVesaDriverId == -1) return MODULE_ERR_MISC; + + return MODULE_ERR_OK; +} + +int VBE_int_GetModeList(void) { tVesa_CallInfo *info; tFarPtr infoPtr; @@ -74,7 +98,6 @@ int Vesa_Install(char **Arguments) int i; // Allocate Info Block - gpVesa_BiosState = VM8086_Init(); info = VM8086_Allocate(gpVesa_BiosState, 512, &infoPtr.seg, &infoPtr.ofs); // Set Requested Version memcpy(info->signature, "VBE2", 4); @@ -88,15 +111,16 @@ int Vesa_Install(char **Arguments) return MODULE_ERR_NOTNEEDED; } - //Log_Debug("VESA", "info->VideoModes = %04x:%04x", info->VideoModes.seg, info->VideoModes.ofs); modes = (Uint16 *) VM8086_GetPointer(gpVesa_BiosState, info->VideoModes.seg, info->VideoModes.ofs); +// VM8086_Deallocate( gpVesa_BiosState, info ); - // Read Modes + // Count Modes for( giVesaModeCount = 0; modes[giVesaModeCount] != 0xFFFF; giVesaModeCount++ ); + giVesaModeCount ++; // First text mode gVesa_Modes = (tVesa_Mode *)malloc( giVesaModeCount * sizeof(tVesa_Mode) ); - Log_Debug("VESA", "%i Modes", giVesaModeCount); - + Log_Debug("VBE", "%i Modes", giVesaModeCount); + // Insert Text Mode gVesa_Modes[0].width = 80; gVesa_Modes[0].height = 25; @@ -108,22 +132,103 @@ int Vesa_Install(char **Arguments) for( i = 1; i < giVesaModeCount; i++ ) { - gVesa_Modes[i].code = modes[i]; + gVesa_Modes[i].code = modes[i-1]; } - -// VM8086_Deallocate( info ); - #if BLINKING_CURSOR - // Create blink timer - gpVesaCursorTimer = Time_AllocateTimer( Vesa_FlipCursor, NULL ); + return 0; +} + +void VBE_int_FillMode_Int(int Index, tVesa_CallModeInfo *vbeinfo, tFarPtr *BufPtr) +{ + tVesa_Mode *mode = &gVesa_Modes[Index]; + + // Get Mode info + gpVesa_BiosState->AX = 0x4F01; + gpVesa_BiosState->CX = mode->code; + gpVesa_BiosState->ES = BufPtr->seg; + gpVesa_BiosState->DI = BufPtr->ofs; + VM8086_Int(gpVesa_BiosState, 0x10); + + if( gpVesa_BiosState->AX != 0x004F ) { + Log_Error("VESA", "Getting info on mode 0x%x failed (AX=0x%x)", + mode->code, gpVesa_BiosState->AX); + return ; + } + + #define S_LOG(s, fld, fmt) LOG(" ."#fld" = "fmt, (s).fld) + LOG("vbeinfo[0x%x] = {", mode->code); + S_LOG(*vbeinfo, attributes, "0x%02x"); + S_LOG(*vbeinfo, winA, "0x%02x"); + S_LOG(*vbeinfo, winB, "0x%02x"); + S_LOG(*vbeinfo, granularity, "0x%04x"); + S_LOG(*vbeinfo, winsize, "0x%04x"); + S_LOG(*vbeinfo, segmentA, "0x%04x"); + S_LOG(*vbeinfo, segmentB, "0x%04x"); + LOG(" .realFctPtr = %04x:%04x", vbeinfo->realFctPtr.seg, vbeinfo->realFctPtr.ofs); + S_LOG(*vbeinfo, pitch, "0x%04x"); + // -- Extended + S_LOG(*vbeinfo, Xres, "%i"); + S_LOG(*vbeinfo, Yres, "%i"); + S_LOG(*vbeinfo, Wchar, "%i"); + S_LOG(*vbeinfo, Ychar, "%i"); + S_LOG(*vbeinfo, planes, "%i"); + S_LOG(*vbeinfo, bpp, "%i"); + S_LOG(*vbeinfo, banks, "%i"); + S_LOG(*vbeinfo, memory_model, "%i"); + S_LOG(*vbeinfo, bank_size, "%i"); + S_LOG(*vbeinfo, image_pages, "%i"); + // -- VBE 1.2+ + LOG(" Red = %i bits at %i", vbeinfo->red_mask, vbeinfo->red_position ); + LOG(" Green = %i bits at %i", vbeinfo->green_mask, vbeinfo->green_position); + LOG(" Blue = %i bits at %i", vbeinfo->blue_mask, vbeinfo->blue_position ); + #if 0 + Uint8 rsv_mask, rsv_position; + Uint8 directcolor_attributes; #endif + // --- VBE 2.0+ + S_LOG(*vbeinfo, physbase, "0x%08x"); + S_LOG(*vbeinfo, offscreen_ptr, "0x%08x"); + S_LOG(*vbeinfo, offscreen_size_kb, "0x%04x"); + // --- VBE 3.0+ + S_LOG(*vbeinfo, lfb_pitch, "0x%04x"); + S_LOG(*vbeinfo, image_count_banked, "%i"); + S_LOG(*vbeinfo, image_count_lfb, "%i"); + LOG("}"); - // Install Device - giVesaDriverId = DevFS_AddDevice( &gVesa_DriverStruct ); - if(giVesaDriverId == -1) return MODULE_ERR_MISC; + mode->flags = FLAG_POPULATED; + if( !(vbeinfo->attributes & 1) ) { + #if DEBUG + Log_Log("VESA", "0x%x - not supported", mode->code); + #endif + mode->width = 0; + mode->height = 0; + mode->bpp = 0; + return ; + } - return MODULE_ERR_OK; -} + // Parse Info + mode->flags |= FLAG_VALID; + if ( (vbeinfo->attributes & 0x90) == 0x90 ) + { + mode->flags |= FLAG_LFB; + mode->framebuffer = vbeinfo->physbase; + mode->fbSize = vbeinfo->Yres*vbeinfo->pitch; + } else { + mode->framebuffer = 0; + mode->fbSize = 0; + } + + mode->pitch = vbeinfo->pitch; + mode->width = vbeinfo->Xres; + mode->height = vbeinfo->Yres; + mode->bpp = vbeinfo->bpp; + + #if DEBUG + Log_Log("VESA", "#%i 0x%x - %ix%ix%i (%x)", + Index, mode->code, mode->width, mode->height, mode->bpp, mode->flags); + #endif + +} void Vesa_int_FillModeList(void) { @@ -133,40 +238,12 @@ void Vesa_int_FillModeList(void) tVesa_CallModeInfo *modeinfo; tFarPtr modeinfoPtr; - modeinfo = VM8086_Allocate(gpVesa_BiosState, 512, &modeinfoPtr.seg, &modeinfoPtr.ofs); + modeinfo = VM8086_Allocate(gpVesa_BiosState, 256, &modeinfoPtr.seg, &modeinfoPtr.ofs); for( i = 1; i < giVesaModeCount; i ++ ) { - // Get Mode info - gpVesa_BiosState->AX = 0x4F01; - gpVesa_BiosState->CX = gVesa_Modes[i].code; - gpVesa_BiosState->ES = modeinfoPtr.seg; - gpVesa_BiosState->DI = modeinfoPtr.ofs; - VM8086_Int(gpVesa_BiosState, 0x10); - - // Parse Info - gVesa_Modes[i].flags = 0; - if ( (modeinfo->attributes & 0x90) == 0x90 ) - { - gVesa_Modes[i].flags |= FLAG_LFB; - gVesa_Modes[i].framebuffer = modeinfo->physbase; - gVesa_Modes[i].fbSize = modeinfo->Yres*modeinfo->pitch; - } else { - gVesa_Modes[i].framebuffer = 0; - gVesa_Modes[i].fbSize = 0; - } - - gVesa_Modes[i].pitch = modeinfo->pitch; - gVesa_Modes[i].width = modeinfo->Xres; - gVesa_Modes[i].height = modeinfo->Yres; - gVesa_Modes[i].bpp = modeinfo->bpp; - - #if DEBUG - Log_Log("VESA", "0x%x - %ix%ix%i", - gVesa_Modes[i].code, gVesa_Modes[i].width, gVesa_Modes[i].height, gVesa_Modes[i].bpp); - #endif - } - -// VM8086_Deallocate( modeinfo ); + VBE_int_FillMode_Int(i, modeinfo, &modeinfoPtr); + } +// VM8086_Deallocate( gpVesa_BiosState, modeinfo ); gbVesaModesChecked = 1; } @@ -192,7 +269,6 @@ const char *csaVESA_IOCtls[] = {DRV_IOCTLNAMES, DRV_VIDEO_IOCTLNAMES, NULL}; int Vesa_IOCtl(tVFS_Node *Node, int ID, void *Data) { int ret; - //Log_Debug("VESA", "Vesa_Ioctl: (Node=%p, ID=%i, Data=%p)", Node, ID, Data); switch(ID) { BASE_IOCTLS(DRV_TYPE_VIDEO, "VESA", VERSION, csaVESA_IOCtls); @@ -249,11 +325,15 @@ int Vesa_Int_SetMode(int mode) gpVesa_BiosState->AX = 0x4F02; gpVesa_BiosState->BX = gVesa_Modes[mode].code; if(gVesa_Modes[mode].flags & FLAG_LFB) { - gpVesa_BiosState->BX |= 0x4000; // Bit 14 - Use LFB + gpVesa_BiosState->BX |= 1 << 14; // Use LFB } + LOG("In : AX=%04x/BX=%04x", + gpVesa_BiosState->AX, gpVesa_BiosState->BX); // Set Mode VM8086_Int(gpVesa_BiosState, 0x10); + + LOG("Out: AX = %04x", gpVesa_BiosState->AX); // Map Framebuffer if( (tVAddr)gpVesa_Framebuffer != VESA_DEFAULT_FRAMEBUFFER ) @@ -261,8 +341,8 @@ int Vesa_Int_SetMode(int mode) giVesaPageCount = (gVesa_Modes[mode].fbSize + 0xFFF) >> 12; gpVesa_Framebuffer = (void*)MM_MapHWPages(gVesa_Modes[mode].framebuffer, giVesaPageCount); - Log_Log("VESA", "Setting mode to %i (%ix%i %ibpp) %p[0x%x] maps %P", - mode, + Log_Log("VESA", "Setting mode to %i 0x%x (%ix%i %ibpp) %p[0x%x] maps %P", + mode, gVesa_Modes[mode].code, gVesa_Modes[mode].width, gVesa_Modes[mode].height, gVesa_Modes[mode].bpp, gpVesa_Framebuffer, giVesaPageCount << 12, gVesa_Modes[mode].framebuffer diff --git a/KernelLand/Modules/Display/VIAVideo/Makefile b/KernelLand/Modules/Display/VIAVideo/Makefile new file mode 100644 index 00000000..c30e4860 --- /dev/null +++ b/KernelLand/Modules/Display/VIAVideo/Makefile @@ -0,0 +1,7 @@ +# +# + +OBJ = main.o +NAME = VIAVideo + +-include ../Makefile.tpl diff --git a/KernelLand/Modules/Display/VIAVideo/common.h b/KernelLand/Modules/Display/VIAVideo/common.h new file mode 100644 index 00000000..d6b5ba1c --- /dev/null +++ b/KernelLand/Modules/Display/VIAVideo/common.h @@ -0,0 +1,22 @@ +/* + */ +#ifndef _VIAVIDEO__COMMON_H_ +#define _VIAVIDEO__COMMON_H_ + +typedef struct sVIAVideo_Dev tVIAVideo_Dev; + +struct sVIAVideo_Dev +{ + tPAddr FramebufferPhys; + tPAddr MMIOPhys; + + void *Framebuffer; + Uint8 *MMIO; + + tDrvUtil_Video_BufInfo BufInfo; + + size_t FBSize; +}; + +#endif + diff --git a/KernelLand/Modules/Display/VIAVideo/main.c b/KernelLand/Modules/Display/VIAVideo/main.c new file mode 100644 index 00000000..2d5ef58d --- /dev/null +++ b/KernelLand/Modules/Display/VIAVideo/main.c @@ -0,0 +1,280 @@ +/* + * Acess2 VIA Video Driver + * - By John Hodge + * + * main.c + * - Driver core + * + * NOTE: Based off the UniChrome driver for X, http://unichrome.sourceforge.net/ + */ +#define DEBUG 0 +#include +#include +#include +#include +#include +#include "common.h" + +#define VERSION VER2(0,1) + +// === CONSTANTS === +const struct sVGA_Timings +{ + int HFP, HSync, HDisplay, HBP; + int VFP, VSync, VDisplay, VBP; +} csaTimings[] = { + {40, 128, 800, 88, 1, 4, 600, 23}, // SVGA @ 60Hz + {24, 136, 1024, 160, 3, 6, 768, 29}, // XGA @ 60Hz + {38, 112, 1280, 248, 1, 3, 1024, 38} // 1280x1024 @ 60Hz +}; + +// === PROTOTYPES === + int VIAVideo_Initialise(char **Arguments); +void VIAVideo_Cleanup(void); + +size_t VIAVideo_Write(tVFS_Node *Node, off_t Offset, size_t Length, const void *Buffer); + int VIAVideo_IOCtl(tVFS_Node *Node, int ID, void *Data); + +void VIAVideo_int_SetMode(const struct sVGA_Timings *Timings, int Depth); +void VIAVideo_int_ResetCRTC(int Index, BOOL Reset); + +static void _SRMask(int Reg, Uint8 Byte, Uint8 Mask); +static void _CRMask(int Reg, Uint8 Byte, Uint8 Mask); + +// === GLOBALS === +MODULE_DEFINE(0, VERSION, VIAVideo, VIAVideo_Initialise, VIAVideo_Cleanup, NULL); +tVFS_NodeType gVIAVideo_NodeType = { + .Write = VIAVideo_Write, + .IOCtl = VIAVideo_IOCtl + }; +tDevFS_Driver gVIAVideo_DriverStruct = { + NULL, "VIAVideo", + {.Type = &gVIAVideo_NodeType} + }; + int giVIAVideo_DriverID; +tVIAVideo_Dev gVIAVideo_Info; + +// === CODE === +int VIAVideo_Initialise(char **Arguments) +{ + int count = 0; + + count += PCI_CountDevices(0x1106, 0x3108); + if(count == 0) return MODULE_ERR_NOTNEEDED; + + + for( int i = 0; (i = PCI_GetDevice(0x1106, 0x3108, i)) != -1; i ++ ) + { + // TODO: Support MMIO + Log_Log("VIAVideo", "BAR0 = 0x%x", PCI_GetBAR(i, 0)); + Log_Log("VIAVideo", "BAR1 = 0x%x", PCI_GetBAR(i, 1)); + Log_Log("VIAVideo", "BAR2 = 0x%x", PCI_GetBAR(i, 2)); + Log_Log("VIAVideo", "BAR3 = 0x%x", PCI_GetBAR(i, 3)); + Log_Log("VIAVideo", "BAR4 = 0x%x", PCI_GetBAR(i, 4)); + Log_Log("VIAVideo", "BAR5 = 0x%x", PCI_GetBAR(i, 5)); + + if( gVIAVideo_Info.FramebufferPhys ) continue ; + + gVIAVideo_Info.FramebufferPhys = PCI_GetBAR(i, 0); + gVIAVideo_Info.MMIOPhys = PCI_GetBAR(i, 1); + + gVIAVideo_Info.Framebuffer = (void*)MM_MapHWPages(gVIAVideo_Info.FramebufferPhys, (1024*768*4)/PAGE_SIZE); + // TODO: Map MMIO + + memset(gVIAVideo_Info.Framebuffer, 128, 1024*4*200); + + gVIAVideo_Info.BufInfo.Framebuffer = gVIAVideo_Info.Framebuffer; + gVIAVideo_Info.BufInfo.Pitch = 1024*4; + gVIAVideo_Info.BufInfo.Width = 1024; + gVIAVideo_Info.BufInfo.Height = 768; + gVIAVideo_Info.BufInfo.Depth = 32; + + } + + VIAVideo_int_SetMode( &csaTimings[1], 32 ); + + // Install Device + giVIAVideo_DriverID = DevFS_AddDevice( &gVIAVideo_DriverStruct ); + if(giVIAVideo_DriverID == -1) return MODULE_ERR_MISC; + + return MODULE_ERR_OK; +} + +void VIAVideo_Cleanup(void) +{ + return ; +} + +size_t VIAVideo_Write(tVFS_Node *Node, off_t Offset, size_t Length, const void *Buffer) +{ + #if 0 + return DrvUtil_Video_WriteLFB(&gVIAVideo_Info.BufInfo, Offset, Length, Buffer); + #endif + return 0; + #if 0 + if( Offset >= gVIAVideo_Info.FBSize ) + return 0; + if( Length > gVIAVideo_Info.FBSize ) + Length = gVIAVideo_Info.FBSize; + if( Offset + Length > gVIAVideo_Info.FBSize ) + Length = gVIAVideo_Info.FBSize - Offset; + + memcpy( (Uint8*)gVIAVideo_Info.Framebuffer + Offset, Buffer, Length ); + + return Length; + #endif +} + +int VIAVideo_IOCtl(tVFS_Node *Node, int ID, void *Data) +{ + return 0; +} + +// --- Modeset! +void VIAVideo_int_SetMode(const struct sVGA_Timings *Timings, int Depth) +{ + int temp; + + // ??? Some Magic (Unichrome - VGACRMask(pVia, 0x17, 0x00, 0x80);) + + // Reset CRTC1 + VIAVideo_int_ResetCRTC(0, TRUE); + + // -- Set framebuffer -- + // Set colour depth bits + // VGASRMask(Crtc, 0x15, {0x00,0x14,0x0C}[Depth=8,16,24/32], 0x1C) + switch(Depth) { + case 8: _SRMask(0x15, 0x00, 0x1C); break; + case 16: _SRMask(0x15, 0x14, 0x1C); break; + case 24: _SRMask(0x15, 0x0C, 0x1C); break; + case 32: _SRMask(0x15, 0x0C, 0x1C); break; + default: return ; + } + // Set line length + { + int pitch = Timings->HDisplay * (Depth/8) / 8; + // (Pitch/8) -> CR13 + CR35&0xE0 + _CRMask(0x13, pitch, 0xFF); + _CRMask(0x35, (pitch>>8)<<5, 0xE0); + } + // - Set frame origin? (->FrameSet(Crtc, X, Y)) + // DWORD Offset in memory + // Stored in CR0D + CR0C + CR34 + CR48&0x03 + + // -- Set CRTC Mode -- + // NOTES: + // - VGA Represents the signal cycle as Display, Blank with Sync anywhere in that + // - Hence, I program the blanking as HBP, Sync, HFP (with the sync in the blanking area) + + // Set mode + // VGAMiscMask(Crtc, (HSyncEnabled ? 0x40 : 0x00), 0x40); + // VGAMiscMask(Crtc, (VSyncEnabled ? 0x80 : 0x00), 0x80); + // HTotal: CR00 + CR36&0x08 = /8-5 + temp = (Timings->HFP + Timings->HSync + Timings->HDisplay + Timings->HBP) / 8 - 5; + _CRMask(0x00, temp, 0xFF); + _CRMask(0x36, (temp>>8)<<3, 0x08); + // HDisplay: CR01 = /8-1 + temp = Timings->HDisplay / 8 - 1; + _CRMask(0x01, temp, 0xFF); + // HBlank Start: CR02 = /8-1 + temp = (Timings->HDisplay) / 8 - 1; + _CRMask(0x02, temp, 0xFF); + // HBlank End: CR03&0x1F + CR05&0x80 + CR33&0x20 = /8-1 + temp = (Timings->HBP + Timings->HSync + Timings->HFP) / 8 - 1; + if( temp >> 7 ) Log_Error("VIA", "HBlank End doesn't fit (%i not 7 bits)", temp); + _CRMask(0x03, temp, 0x1F); + _CRMask(0x05, (temp>>5)<<7, 0x80); + _CRMask(0x33, (temp>>6)<<5, 0x20); + // HSync Start: CR04 + CR33&0x10 = /8 + temp = (Timings->HDisplay + Timings->HBP) / 8; + _CRMask(0x04, temp, 0xFF); + _CRMask(0x33, (temp>>8)<<4, 0x10); + // HSync End: CR05&0x1F = /8 + temp = (Timings->HSync) / 8; + _CRMask(0x05, temp, 0x1F); + // VTotal: CR06 + CR07&0x01 + CR07&0x20 + CR35&0x01 = -2 + temp = (Timings->VFP + Timings->VBP + Timings->VSync + Timings->VDisplay) - 2; + _CRMask(0x06, temp, 0xFF); + _CRMask(0x07, (temp>>8)<<0, 0x01); + _CRMask(0x07, (temp>>9)<<5, 0x20); + _CRMask(0x35, (temp>>10)<<0, 0x01); + // VDisplay: CR12 + CR07&0x02 + CR07&0x40 + CR35&0x04 = -1 + temp = (Timings->VDisplay) - 1; + _CRMask(0x12, temp, 0xFF); + _CRMask(0x07, (temp>>8)<<1, 0x02); + _CRMask(0x07, (temp>>9)<<6, 0x40); + _CRMask(0x07, (temp>>10)<<2, 0x04); + // 0: CR0C + CR0D + CD34 + CR48&0x03 ("Primary starting address") + temp = 0; + _CRMask(0x0C, temp, 0xFF); + _CRMask(0x0D, (temp>>8), 0xFF); + _CRMask(0x34, (temp>>16), 0xFF); + _CRMask(0x48, (temp>>24), 0x03); + // VSyncStart: CR10 + CR07&0x04 + CR07&0x80 + CR35&0x02 + temp = (Timings->VDisplay + Timings->HBP); + _CRMask(0x10, temp, 0xFF); + _CRMask(0x07, (temp>>8)<<2, 0x04); + _CRMask(0x07, (temp>>9)<<7, 0x80); + _CRMask(0x35, (temp>>10)<<1, 0x02); + // VSyncEnd: CR11&0x0F + temp = (Timings->VSync); + _CRMask(0x11, temp, 0x0F); + // 0x3FFF: CR18 + CR07&0x10 + CR09&0x40 + CR33&0x06 + CR35&0x10 ("line compare") + temp = 0x3FFF; + _CRMask(0x18, temp, 0xFF); + _CRMask(0x07, (temp>>8)<<4, 0x10); + _CRMask(0x09, (temp>>9)<<6, 0x40); + _CRMask(0x33, (temp>>10)<<1, 0x06); + _CRMask(0x35, (temp>>12)<<4, 0x10); + // 0: CR09&0x1F ("Maximum scanline") + temp = 0; + _CRMask(0x09, temp, 0x1F); + // 0: Cursor location + temp = 0; + _CRMask(0x14, temp, 0xFF); + // VBlankStart: CR15 + CR07&0x08 + CR09&0x20 + CR35&0x08 = -1 + temp = (Timings->VDisplay) - 1; + _CRMask(0x15, temp, 0xFF); + _CRMask(0x07, (temp>>8)<<3, 0x08); + _CRMask(0x09, (temp>>9)<<5, 0x20); + _CRMask(0x35, (temp>>10)<<3, 0x08); + // VBlankEnd: CR16 = -1 + temp = (Timings->VBP + Timings->VSync + Timings->VFP) - 1; + _CRMask(0x16, temp, 0xFF); + // 0: CR08 (Preset Row Scan Register) + _CRMask(0x08, 0, 0xFF); + // 0: CR32 (???) + _CRMask(0x32, 0, 0xFF); + // 0: CR33&0xC8 + _CRMask(0x33, 0, 0xC8); + + // Set scaling? + + // Disable CRTC reset + VIAVideo_int_ResetCRTC(0, FALSE); +} + +void VIAVideo_int_ResetCRTC(int Index, BOOL Reset) +{ + // VGASRMask(Crtc, 0x00, (Reset ? 0x00 : 0x02), 0x02); + _SRMask(0x00, (Reset ? 0x00 : 0x02), 0x02); +} + +void _SRMask(int Reg, Uint8 Byte, Uint8 Mask) +{ + Uint8 cv = 0; + outb(0x3C4, Reg); + if(Mask != 0xFF) cv = inb(0x3C5) & ~Mask; + cv |= Byte & Mask; + outb(0x3C5, cv); +} + +void _CRMask(int Reg, Uint8 Byte, Uint8 Mask) +{ + Uint8 cv = 0; + outb(0x3D4, Reg); + if(Mask != 0xFF) cv = inb(0x3D5) & ~Mask; + cv |= Byte & Mask; + outb(0x3D5, cv); +} + diff --git a/Usermode/Applications/init_src/Makefile b/Usermode/Applications/init_src/Makefile index c8a6ddb5..df032bcd 100644 --- a/Usermode/Applications/init_src/Makefile +++ b/Usermode/Applications/init_src/Makefile @@ -5,7 +5,6 @@ CPPFLAGS += CFLAGS += -Wall -Werror -O3 LDFLAGS += -# -lspiderscript BIN = init OBJ = main.o diff --git a/Usermode/Applications/init_src/main.c b/Usermode/Applications/init_src/main.c index 4d66654c..c18e5f8c 100644 --- a/Usermode/Applications/init_src/main.c +++ b/Usermode/Applications/init_src/main.c @@ -4,50 +4,16 @@ #include #include #include -//#include //#include "common.h" // === CONSTANTS === #define NUM_TERMS 4 #define DEFAULT_TERMINAL "/Devices/VTerm/0" #define DEFAULT_SHELL "/Acess/SBin/login" -#define DEFAULT_SCRIPT "/Acess/Conf/BootConf.isc" #define ARRAY_SIZE(x) ((sizeof(x))/(sizeof((x)[0]))) // === PROTOTYPES === -/* -tSpiderVariable *Script_System_IO_Open(tSpiderScript *, int, tSpiderVariable *); -*/ - -// === GLOBALS === -/* -tSpiderFunction gaScriptNS_IO_Fcns[] = { - {"Open", Script_System_IO_Open} -}; -tSpiderNamespace gaScriptNS_System[] = { - { - "IO", - 0, NULL, - ARRAY_SIZE(gaScriptNS_IO_Fcns), gaScriptNS_IO_Fcns, - 0, NULL - } -}; - -tSpiderNamespace gaScriptNamespaces[] = { - { - "System", - ARRAY_SIZE(gaScriptNS_System), gaScriptNS_System, - 0, NULL, - 0, NULL - } -}; - -tSpiderVariant gScriptVariant = { - "init", 0, - ARRAY_SIZE(gaScriptNamespaces), gaScriptNamespaces -}; -*/ // === CODE === /** @@ -85,26 +51,3 @@ int main(int argc, char *argv[]) return 42; } -/** - * \brief Reads and parses the boot configuration script - * \param Filename File to parse and execute - */ -void ExecuteScript(const char *Filename) -{ - /* - tSpiderScript *script; - script = SpiderScript_ParseFile(&gScriptVariant, Filename); - SpiderScript_ExecuteMethod(script, ""); - SpiderScript_Free(script); - */ -} - -/** - * \brief Open a file - */ -/* -tSpiderVariable *Script_System_IO_Open(tSpiderScript *Script, int NArgs, tSpiderVariable *Args) -{ - return NULL; -} -*/ diff --git a/Usermode/Libraries/libspiderscript.so_src/Makefile b/Usermode/Libraries/libspiderscript.so_src/Makefile deleted file mode 100644 index 28382cad..00000000 --- a/Usermode/Libraries/libspiderscript.so_src/Makefile +++ /dev/null @@ -1,13 +0,0 @@ -# Acess 2 -# - -include ../Makefile.cfg - -CPPFLAGS += -CFLAGS += -Wall -LDFLAGS += -lc -lgcc -soname libspiderscript.so --no-allow-shlib-undefined - -OBJ = main.o lex.o parse.o ast.o exec_ast.o exports.o -BIN = libspiderscript.so - -include ../Makefile.tpl diff --git a/Usermode/Libraries/libspiderscript.so_src/Scripts/sample.isc b/Usermode/Libraries/libspiderscript.so_src/Scripts/sample.isc deleted file mode 100644 index d9ec0205..00000000 --- a/Usermode/Libraries/libspiderscript.so_src/Scripts/sample.isc +++ /dev/null @@ -1,44 +0,0 @@ -# diff --git a/Usermode/Libraries/libspiderscript.so_src/Scripts/sample_static.ssc b/Usermode/Libraries/libspiderscript.so_src/Scripts/sample_static.ssc deleted file mode 100644 index f490fb82..00000000 --- a/Usermode/Libraries/libspiderscript.so_src/Scripts/sample_static.ssc +++ /dev/null @@ -1,29 +0,0 @@ -# diff --git a/Usermode/Libraries/libspiderscript.so_src/ast.c b/Usermode/Libraries/libspiderscript.so_src/ast.c deleted file mode 100644 index 12f9f775..00000000 --- a/Usermode/Libraries/libspiderscript.so_src/ast.c +++ /dev/null @@ -1,744 +0,0 @@ -/* - * Acess2 Init - * - Script AST Manipulator - */ -#include -#include -#include -#include "common.h" -#include "ast.h" - -// === IMPORTS === -extern void SyntaxError(tParser *Parser, int bFatal, const char *Message, ...); - -// === CODE === -/** - * \brief Append a function to a script - */ -int AST_AppendFunction(tSpiderScript *Script, const char *Name, int ReturnType, tAST_Node *Args, tAST_Node *Code) -{ - tScript_Function *fcn; - int arg_count = 0, arg_bytes = 0; - tAST_Node *arg; - - // Count and size arguments - for(arg = Args; arg; arg = arg->NextSibling) - { - arg_count ++; - arg_bytes += sizeof(fcn->Arguments[0]) + strlen(Args->DefVar.Name) + 1; - } - - // Allocate information - fcn = malloc( sizeof(tScript_Function) + arg_bytes + strlen(Name) + 1 ); - if(!fcn) return -1; - fcn->Next = NULL; - fcn->Name = (char*)&fcn->Arguments[arg_count]; - strcpy(fcn->Name, Name); - fcn->ReturnType = ReturnType; - fcn->ArgumentCount = arg_count; - fcn->ASTFcn = Code; - fcn->BCFcn = NULL; - - // Set arguments - arg_bytes = strlen(Name) + 1; // Used as an offset into fcn->Name - arg_count = 0; - for(arg = Args; arg; arg = arg->NextSibling) - { - fcn->Arguments[arg_count].Name = fcn->Name + arg_bytes; - strcpy(fcn->Arguments[arg_count].Name, arg->DefVar.Name); - fcn->Arguments[arg_count].Type = arg->DefVar.DataType; - arg_bytes += strlen(arg->DefVar.Name) + 1; - arg_count ++; - } - - if(Script->LastFunction == NULL) { - Script->Functions = Script->LastFunction = fcn; - } - else { - Script->LastFunction->Next = fcn; - Script->LastFunction = fcn; - } - - return 0; -} - -/** - * \name Node Manipulation - * \{ - */ -#define WRITE_N(_buffer, _offset, _len, _dataptr) do { \ - if(_buffer) memcpy((char*)_buffer + _offset, _dataptr, _len);\ - _offset += _len; \ -} while(0) - -#define WRITE_8(_buffer, _offset, _val) do {\ - uint8_t v = (_val);\ - WRITE_N(_buffer, _offset, 1, &v);\ -} while(0) -#define WRITE_16(_buffer, _offset, _val) do {\ - uint16_t v = (_val);\ - WRITE_N(_buffer, _offset, 2, &v);\ -} while(0) -#define WRITE_32(_buffer, _offset, _val) do {\ - uint32_t v = (_val);\ - WRITE_N(_buffer, _offset, 4, &v);\ -} while(0) -#define WRITE_64(_buffer, _offset, _val) do {\ - uint64_t v = (_val);\ - WRITE_N(_buffer, _offset, 8, &v);\ -} while(0) -#define WRITE_REAL(_buffer, _offset, _val) do {\ - double v = (_val);\ - WRITE_N(_buffer, _offset, sizeof(double), &v);\ -} while(0) - -#define WRITE_STR(_buffer, _offset, _string) do {\ - int len = strlen(_string);\ - WRITE_16(_buffer, _offset, len);\ - WRITE_N(_buffer, _offset, len, _string);\ - if((_offset & 1) == 1)WRITE_8(_buffer, _offset, 0); \ - if((_offset & 3) == 2)WRITE_16(_buffer, _offset, 0); \ -} while(0) -#define WRITE_NODELIST(_buffer, _offset, _listHead) do {\ - tAST_Node *node; \ - size_t ptr = -1;\ - for(node=(_listHead); node; node = node->NextSibling) {\ - ptr = _offset;\ - _offset += AST_WriteNode(_buffer, _offset, node); \ - WRITE_32(_buffer, ptr, ptr); \ - } \ - if(ptr != -1){ptr -= 4; WRITE_32(_buffer, ptr, 0);} \ -} while(0) - -/** - * \brief Writes a script dump to a buffer - * \return Size of encoded data - * \note If \a Buffer is NULL, no write is done, but the size is still returned - */ -size_t AST_WriteScript(void *Buffer, tSpiderScript *Script) -{ - tScript_Function *fcn; - size_t ret = 0, ptr = 0; - int i; - - for( fcn = Script->Functions; fcn; fcn = fcn->Next ) - { -// printf("fcn = %p, fcn->Name = %p\n", fcn, fcn->Name); - ptr = ret; - WRITE_32(Buffer, ret, 0); // Next - WRITE_STR(Buffer, ret, fcn->Name); - WRITE_32(Buffer, ret, fcn->ArgumentCount); - for( i = 0; i < fcn->ArgumentCount; i ++ ) - { - WRITE_16(Buffer, ret, fcn->Arguments[i].Type); - WRITE_STR(Buffer, ret, fcn->Arguments[i].Name); - } - ret += AST_WriteNode(Buffer, ret, fcn->ASTFcn); - WRITE_32(Buffer, ptr, ret); // Actually set `Next` - } - if( ptr ) - { - ptr -= 4; - WRITE_32(Buffer, ptr, 0); // Clear next for final - } - - return ret; -} - -/** - * \brief Write a node to a file - */ -size_t AST_WriteNode(void *Buffer, size_t Offset, tAST_Node *Node) -{ - size_t baseOfs = Offset; - - if(!Node) { - //fprintf(stderr, "Possible Bug - NULL passed to AST_WriteNode\n"); - WRITE_32(Buffer, Offset, 0); - WRITE_16(Buffer, Offset, NODETYPE_NOP); - WRITE_16(Buffer, Offset, 0); // Line (0) - return 0; - } - - WRITE_32(Buffer, Offset, 0); // Next - WRITE_16(Buffer, Offset, Node->Type); - // TODO: Scan the buffer for the location of the filename (with NULL byte) - // else, write the string at the end of the node - WRITE_16(Buffer, Offset, Node->Line); // Line - //WRITE_32(Buffer, Offset, 0); // File - - switch(Node->Type) - { - // Block of code - case NODETYPE_BLOCK: - WRITE_NODELIST(Buffer, Offset, Node->Block.FirstChild); - break; - - // Function Call - case NODETYPE_METHODCALL: - Offset += AST_WriteNode(Buffer, Offset, Node->FunctionCall.Object); - case NODETYPE_FUNCTIONCALL: - case NODETYPE_CREATEOBJECT: - // TODO: Search for the same function name and add a pointer - WRITE_STR(Buffer, Offset, Node->FunctionCall.Name); - WRITE_NODELIST(Buffer, Offset, Node->FunctionCall.FirstArg); - break; - - // If node - case NODETYPE_IF: - Offset += AST_WriteNode(Buffer, Offset, Node->If.Condition); - Offset += AST_WriteNode(Buffer, Offset, Node->If.True); - Offset += AST_WriteNode(Buffer, Offset, Node->If.False); - break; - - // Looping Construct (For loop node) - case NODETYPE_LOOP: - WRITE_8(Buffer, Offset, Node->For.bCheckAfter); - WRITE_STR(Buffer, Offset, Node->For.Tag); - Offset += AST_WriteNode(Buffer, Offset, Node->For.Init); - Offset += AST_WriteNode(Buffer, Offset, Node->For.Condition); - Offset += AST_WriteNode(Buffer, Offset, Node->For.Increment); - Offset += AST_WriteNode(Buffer, Offset, Node->For.Code); - break; - - // Asignment - case NODETYPE_ASSIGN: - WRITE_8(Buffer, Offset, Node->Assign.Operation); - Offset += AST_WriteNode(Buffer, Offset, Node->Assign.Dest); - Offset += AST_WriteNode(Buffer, Offset, Node->Assign.Value); - break; - - // Casting - case NODETYPE_CAST: - WRITE_8(Buffer, Offset, Node->Cast.DataType); - Offset += AST_WriteNode(Buffer, Offset, Node->Cast.Value); - break; - - // Define a variable - case NODETYPE_DEFVAR: - WRITE_8(Buffer, Offset, Node->DefVar.DataType); - // TODO: Duplicate compress the strings - WRITE_STR(Buffer, Offset, Node->DefVar.Name); - - WRITE_NODELIST(Buffer, Offset, Node->DefVar.LevelSizes); - Offset += AST_WriteNode(Buffer, Offset, Node->DefVar.InitialValue); - break; - - // Scope Reference - case NODETYPE_SCOPE: - case NODETYPE_ELEMENT: - WRITE_STR(Buffer, Offset, Node->Scope.Name); - Offset += AST_WriteNode(Buffer, Offset, Node->UniOp.Value); - break; - - // Unary Operations - case NODETYPE_RETURN: - case NODETYPE_BWNOT: - case NODETYPE_LOGICALNOT: - case NODETYPE_NEGATE: - case NODETYPE_POSTINC: - case NODETYPE_POSTDEC: - Offset += AST_WriteNode(Buffer, Offset, Node->UniOp.Value); - break; - - // Binary Operations - case NODETYPE_INDEX: - case NODETYPE_ADD: - case NODETYPE_SUBTRACT: - case NODETYPE_MULTIPLY: - case NODETYPE_DIVIDE: - case NODETYPE_MODULO: - case NODETYPE_BITSHIFTLEFT: - case NODETYPE_BITSHIFTRIGHT: - case NODETYPE_BITROTATELEFT: - case NODETYPE_BWAND: case NODETYPE_LOGICALAND: - case NODETYPE_BWOR: case NODETYPE_LOGICALOR: - case NODETYPE_BWXOR: case NODETYPE_LOGICALXOR: - case NODETYPE_EQUALS: - case NODETYPE_LESSTHAN: case NODETYPE_LESSTHANEQUAL: - case NODETYPE_GREATERTHAN: case NODETYPE_GREATERTHANEQUAL: - Offset += AST_WriteNode(Buffer, Offset, Node->BinOp.Left); - Offset += AST_WriteNode(Buffer, Offset, Node->BinOp.Right); - break; - - // Node types with no children - case NODETYPE_NOP: - break; - case NODETYPE_VARIABLE: - case NODETYPE_CONSTANT: - case NODETYPE_BREAK: - case NODETYPE_CONTINUE: - // TODO: De-Duplicate the strings - WRITE_STR(Buffer, Offset, Node->Variable.Name); - break; - case NODETYPE_STRING: - WRITE_32(Buffer, Offset, Node->Constant.String.Length); - WRITE_N(Buffer, Offset, Node->Constant.String.Length, Node->Constant.String.Data); - break; - case NODETYPE_INTEGER: - WRITE_64(Buffer, Offset, Node->Constant.Integer); - break; - case NODETYPE_REAL: - WRITE_REAL(Buffer, Offset, Node->Constant.Real); - break; - - //default: - // fprintf(stderr, "AST_WriteNode: Unknown node type %i\n", Node->Type); - // break; - } - - return Offset - baseOfs; -} - -/** - * \brief Free a node and all subnodes - */ -void AST_FreeNode(tAST_Node *Node) -{ - tAST_Node *node; - - if(!Node) return ; - - // Referenced counted file name - (*(int*)(Node->File - sizeof(int))) -= 1; - if( *(int*)(Node->File - sizeof(int)) == 0 ) - free( (void*)(Node->File - sizeof(int)) ); - - switch(Node->Type) - { - // Block of code - case NODETYPE_BLOCK: - for( node = Node->Block.FirstChild; node; ) - { - tAST_Node *savedNext = node->NextSibling; - AST_FreeNode(node); - node = savedNext; - } - break; - - // Function Call - case NODETYPE_METHODCALL: - AST_FreeNode(Node->FunctionCall.Object); - case NODETYPE_FUNCTIONCALL: - case NODETYPE_CREATEOBJECT: - for( node = Node->FunctionCall.FirstArg; node; ) - { - tAST_Node *savedNext = node->NextSibling; - AST_FreeNode(node); - node = savedNext; - } - break; - - // If node - case NODETYPE_IF: - AST_FreeNode(Node->If.Condition); - AST_FreeNode(Node->If.True); - AST_FreeNode(Node->If.False); - break; - - // Looping Construct (For loop node) - case NODETYPE_LOOP: - AST_FreeNode(Node->For.Init); - AST_FreeNode(Node->For.Condition); - AST_FreeNode(Node->For.Increment); - AST_FreeNode(Node->For.Code); - break; - - // Asignment - case NODETYPE_ASSIGN: - AST_FreeNode(Node->Assign.Dest); - AST_FreeNode(Node->Assign.Value); - break; - - // Casting - case NODETYPE_CAST: - AST_FreeNode(Node->Cast.Value); - break; - - case NODETYPE_SCOPE: - case NODETYPE_ELEMENT: - AST_FreeNode(Node->Scope.Element); - break; - - // Define a variable - case NODETYPE_DEFVAR: - for( node = Node->DefVar.LevelSizes; node; ) - { - tAST_Node *savedNext = node->NextSibling; - AST_FreeNode(node); - node = savedNext; - } - AST_FreeNode(Node->DefVar.InitialValue); - break; - - // Unary Operations - case NODETYPE_RETURN: - case NODETYPE_BWNOT: - case NODETYPE_LOGICALNOT: - case NODETYPE_NEGATE: - case NODETYPE_POSTINC: - case NODETYPE_POSTDEC: - AST_FreeNode(Node->UniOp.Value); - break; - - // Binary Operations - case NODETYPE_INDEX: - case NODETYPE_ADD: - case NODETYPE_SUBTRACT: - case NODETYPE_MULTIPLY: - case NODETYPE_DIVIDE: - case NODETYPE_MODULO: - case NODETYPE_BITSHIFTLEFT: - case NODETYPE_BITSHIFTRIGHT: - case NODETYPE_BITROTATELEFT: - case NODETYPE_BWAND: case NODETYPE_LOGICALAND: - case NODETYPE_BWOR: case NODETYPE_LOGICALOR: - case NODETYPE_BWXOR: case NODETYPE_LOGICALXOR: - case NODETYPE_EQUALS: - case NODETYPE_LESSTHAN: case NODETYPE_LESSTHANEQUAL: - case NODETYPE_GREATERTHAN: case NODETYPE_GREATERTHANEQUAL: - AST_FreeNode( Node->BinOp.Left ); - AST_FreeNode( Node->BinOp.Right ); - break; - - // Node types with no children - case NODETYPE_NOP: break; - case NODETYPE_VARIABLE: break; - case NODETYPE_CONSTANT: break; - case NODETYPE_BREAK: - case NODETYPE_CONTINUE: break; - - case NODETYPE_STRING: - case NODETYPE_INTEGER: - case NODETYPE_REAL: - if( Node->ValueCache ) - SpiderScript_DereferenceValue(Node->ValueCache); - Node->ValueCache = NULL; - break; - } - free( Node ); -} - -tAST_Node *AST_int_AllocateNode(tParser *Parser, int Type, int ExtraSize) -{ - tAST_Node *ret = malloc( sizeof(tAST_Node) + ExtraSize ); - ret->NextSibling = NULL; - ret->File = Parser->Filename; *(int*)(Parser->Filename - sizeof(int)) += 1; - ret->Line = Parser->CurLine; - ret->Type = Type; - - // Runtime Caching - ret->BlockState = NULL; - ret->BlockIdent = 0; - ret->ValueCache = NULL; - - return ret; -} - -tAST_Node *AST_NewCodeBlock(tParser *Parser) -{ - tAST_Node *ret = AST_int_AllocateNode(Parser, NODETYPE_BLOCK, 0 ); - - ret->Block.FirstChild = NULL; - ret->Block.LastChild = NULL; - - return ret; -} - -void AST_AppendNode(tAST_Node *Parent, tAST_Node *Child) -{ - // Ignore NULL children - if( !Child ) return ; - - Child->NextSibling = NULL; - switch( Parent->Type ) - { - case NODETYPE_BLOCK: - if(Parent->Block.FirstChild == NULL) { - Parent->Block.FirstChild = Parent->Block.LastChild = Child; - } - else { - Parent->Block.LastChild->NextSibling = Child; - Parent->Block.LastChild = Child; - } - break; - case NODETYPE_DEFVAR: - if(Parent->DefVar.LevelSizes == NULL) { - Parent->DefVar.LevelSizes = Parent->DefVar.LevelSizes_Last = Child; - } - else { - Parent->DefVar.LevelSizes_Last->NextSibling = Child; - Parent->DefVar.LevelSizes_Last = Child; - } - break; - default: - fprintf(stderr, "BUG REPORT: AST_AppendNode on an invalid node type (%i)\n", Parent->Type); - break; - } -} - -tAST_Node *AST_NewIf(tParser *Parser, tAST_Node *Condition, tAST_Node *True, tAST_Node *False) -{ - tAST_Node *ret = AST_int_AllocateNode(Parser, NODETYPE_IF, 0); - ret->If.Condition = Condition; - ret->If.True = True; - ret->If.False = False; - return ret; -} - -tAST_Node *AST_NewLoop(tParser *Parser, const char *Tag, tAST_Node *Init, int bPostCheck, tAST_Node *Condition, tAST_Node *Increment, tAST_Node *Code) -{ - tAST_Node *ret; - if(!Tag) Tag = ""; - // NOTE: The +3) & ~3 is to align the size to 4 bytes, and shut valgrind up - // - GCC sometimes inlines strlen as a loop of dword reads, triggering valgrind - ret = AST_int_AllocateNode(Parser, NODETYPE_LOOP, (strlen(Tag) + 1 + 3) & ~3); - ret->For.Init = Init; - ret->For.bCheckAfter = !!bPostCheck; - ret->For.Condition = Condition; - ret->For.Increment = Increment; - ret->For.Code = Code; - strcpy(ret->For.Tag, Tag); - return ret; -} - -tAST_Node *AST_NewAssign(tParser *Parser, int Operation, tAST_Node *Dest, tAST_Node *Value) -{ - tAST_Node *ret = AST_int_AllocateNode(Parser, NODETYPE_ASSIGN, 0); - - if( Dest->Type != NODETYPE_VARIABLE && Dest->Type != NODETYPE_ELEMENT ) { - free(ret); - SyntaxError(Parser, 1, "Assign target is not a variable or attribute (instead %i)", - Dest->Type); - AST_FreeNode(Dest); - AST_FreeNode(Value); - return NULL; - } - - ret->Assign.Operation = Operation; - ret->Assign.Dest = Dest; - ret->Assign.Value = Value; - - return ret; -} - -tAST_Node *AST_NewCast(tParser *Parser, int Target, tAST_Node *Value) -{ - tAST_Node *ret = AST_int_AllocateNode(Parser, NODETYPE_CAST, 0); - - ret->Cast.DataType = Target; - ret->Cast.Value = Value; - - return ret; -} - -tAST_Node *AST_NewBinOp(tParser *Parser, int Operation, tAST_Node *Left, tAST_Node *Right) -{ - tAST_Node *ret = AST_int_AllocateNode(Parser, Operation, 0); - - ret->BinOp.Left = Left; - ret->BinOp.Right = Right; - - return ret; -} - -/** - */ -tAST_Node *AST_NewUniOp(tParser *Parser, int Operation, tAST_Node *Value) -{ - tAST_Node *ret = AST_int_AllocateNode(Parser, Operation, 0); - - ret->UniOp.Value = Value; - - return ret; -} - -tAST_Node *AST_NewBreakout(tParser *Parser, int Type, const char *DestTag) -{ - int len = (DestTag ? strlen(DestTag) : 0); - tAST_Node *ret = AST_int_AllocateNode(Parser, Type, len + 1); - - if( DestTag ) - strcpy(ret->Variable.Name, DestTag); - else - ret->Variable.Name[0] = '\0'; - - return ret; -} - -tAST_Node *AST_NewNop(tParser *Parser) -{ - tAST_Node *ret = AST_int_AllocateNode(Parser, NODETYPE_NOP, 0); - - return ret; -} - -/** - * \brief Create a new string node - */ -tAST_Node *AST_NewString(tParser *Parser, const char *String, int Length) -{ - tAST_Node *ret = AST_int_AllocateNode(Parser, NODETYPE_STRING, Length + 1); - - ret->Constant.Type = SS_DATATYPE_STRING; - ret->Constant.ReferenceCount = 1; - ret->Constant.String.Length = Length; - memcpy(ret->Constant.String.Data, String, Length); - ret->Constant.String.Data[Length] = '\0'; - - return ret; -} - -/** - * \brief Create a new integer node - */ -tAST_Node *AST_NewInteger(tParser *Parser, int64_t Value) -{ - tAST_Node *ret = AST_int_AllocateNode(Parser, NODETYPE_INTEGER, 0); - ret->Constant.Type = SS_DATATYPE_INTEGER; - ret->Constant.ReferenceCount = 1; - ret->Constant.Integer = Value; - return ret; -} - -/** - * \brief Create a new real number node - */ -tAST_Node *AST_NewReal(tParser *Parser, double Value) -{ - tAST_Node *ret = AST_int_AllocateNode(Parser, NODETYPE_REAL, 0); - ret->Constant.Type = SS_DATATYPE_REAL; - ret->Constant.ReferenceCount = 1; - ret->Constant.Real = Value; - return ret; -} - -/** - * \brief Create a new variable reference node - */ -tAST_Node *AST_NewVariable(tParser *Parser, const char *Name) -{ - tAST_Node *ret = AST_int_AllocateNode(Parser, NODETYPE_VARIABLE, strlen(Name) + 1 ); - strcpy(ret->Variable.Name, Name); - return ret; -} - -/** - * \brief Create a new variable definition node - */ -tAST_Node *AST_NewDefineVar(tParser *Parser, int Type, const char *Name) -{ - tAST_Node *ret = AST_int_AllocateNode(Parser, NODETYPE_DEFVAR, strlen(Name) + 1 ); - - ret->DefVar.DataType = Type; - ret->DefVar.LevelSizes = NULL; - ret->DefVar.LevelSizes_Last = NULL; - ret->DefVar.InitialValue = NULL; - strcpy(ret->DefVar.Name, Name); - - return ret; -} - -/** - * \brief Create a new runtime constant reference node - */ -tAST_Node *AST_NewConstant(tParser *Parser, const char *Name) -{ - tAST_Node *ret = AST_int_AllocateNode(Parser, NODETYPE_CONSTANT, strlen(Name) + 1 ); - - strcpy(ret->Variable.Name, Name); - - return ret; -} - -/** - * \brief Create a function call node - * \note Argument list is manipulated using AST_AppendFunctionCallArg - */ -tAST_Node *AST_NewFunctionCall(tParser *Parser, const char *Name) -{ - tAST_Node *ret = AST_int_AllocateNode(Parser, NODETYPE_FUNCTIONCALL, strlen(Name) + 1 ); - - ret->FunctionCall.Object = NULL; - ret->FunctionCall.FirstArg = NULL; - ret->FunctionCall.LastArg = NULL; - ret->FunctionCall.NumArgs = 0; - strcpy(ret->FunctionCall.Name, Name); - - return ret; -} -tAST_Node *AST_NewMethodCall(tParser *Parser, tAST_Node *Object, const char *Name) -{ - tAST_Node *ret = AST_int_AllocateNode(Parser, NODETYPE_METHODCALL, strlen(Name) + 1 ); - - ret->FunctionCall.Object = Object; - ret->FunctionCall.FirstArg = NULL; - ret->FunctionCall.LastArg = NULL; - ret->FunctionCall.NumArgs = 0; - strcpy(ret->FunctionCall.Name, Name); - - return ret; -} - -tAST_Node *AST_NewCreateObject(tParser *Parser, const char *Name) -{ - tAST_Node *ret = AST_int_AllocateNode(Parser, NODETYPE_CREATEOBJECT, strlen(Name) + 1 ); - - ret->FunctionCall.Object = NULL; - ret->FunctionCall.FirstArg = NULL; - ret->FunctionCall.LastArg = NULL; - ret->FunctionCall.NumArgs = 0; - strcpy(ret->FunctionCall.Name, Name); - - return ret; -} - -/** - * \brief Append an argument to a function call - */ -void AST_AppendFunctionCallArg(tAST_Node *Node, tAST_Node *Arg) -{ - if( Node->Type != NODETYPE_FUNCTIONCALL - && Node->Type != NODETYPE_CREATEOBJECT - && Node->Type != NODETYPE_METHODCALL) - { - fprintf(stderr, "BUG REPORT: AST_AppendFunctionCallArg on an invalid node type (%i)\n", Node->Type); - return ; - } - - if(Node->FunctionCall.LastArg) { - Node->FunctionCall.LastArg->NextSibling = Arg; - Node->FunctionCall.LastArg = Arg; - } - else { - Node->FunctionCall.FirstArg = Arg; - Node->FunctionCall.LastArg = Arg; - } - Node->FunctionCall.NumArgs ++; -} - -/** - * \brief Add a scope node - */ -tAST_Node *AST_NewScopeDereference(tParser *Parser, const char *Name, tAST_Node *Child) -{ - tAST_Node *ret = AST_int_AllocateNode(Parser, NODETYPE_SCOPE, strlen(Name) + 1 ); - ret->Scope.Element = Child; - strcpy(ret->Scope.Name, Name); - return ret; -} - -/** - * \brief Add a scope node - */ -tAST_Node *AST_NewClassElement(tParser *Parser, tAST_Node *Object, const char *Name) -{ - tAST_Node *ret = AST_int_AllocateNode(Parser, NODETYPE_ELEMENT, strlen(Name) + 1 ); - ret->Scope.Element = Object; - strcpy(ret->Scope.Name, Name); - return ret; -} - -/** - * \} - */ diff --git a/Usermode/Libraries/libspiderscript.so_src/ast.h b/Usermode/Libraries/libspiderscript.so_src/ast.h deleted file mode 100644 index 8ee56d77..00000000 --- a/Usermode/Libraries/libspiderscript.so_src/ast.h +++ /dev/null @@ -1,235 +0,0 @@ -/* - */ -#ifndef _AST_H_ -#define _AST_H_ - -#include -#include "tokens.h" - -typedef enum eAST_NodeTypes tAST_NodeType; -typedef struct sAST_Script tAST_Script; -typedef struct sAST_Function tAST_Function; -typedef struct sAST_Node tAST_Node; -typedef struct sAST_BlockState tAST_BlockState; -typedef struct sAST_Variable tAST_Variable; - -/** - * \brief Node Types - */ -enum eAST_NodeTypes -{ - NODETYPE_NOP, - - NODETYPE_BLOCK, //!< Node Block - - NODETYPE_VARIABLE, //!< Variable - NODETYPE_CONSTANT, //!< Runtime Constant - NODETYPE_STRING, //!< String Constant - NODETYPE_INTEGER, //!< Integer Constant - NODETYPE_REAL, //!< Real Constant - - NODETYPE_DEFVAR, //!< Define a variable (Variable) - NODETYPE_SCOPE, //!< Dereference a Namespace/Class static - NODETYPE_ELEMENT, //!< Reference a class attribute - NODETYPE_CAST, //!< Cast a value to another (Uniop) - - NODETYPE_RETURN, //!< Return from a function (reserved word) - NODETYPE_BREAK, //!< Break out of a loop - NODETYPE_CONTINUE, //!< Next loop iteration - NODETYPE_ASSIGN, //!< Variable assignment operator - NODETYPE_POSTINC, //!< Post-increment (i++) - Uniop - NODETYPE_POSTDEC, //!< Post-decrement (i--) - Uniop - NODETYPE_FUNCTIONCALL, //!< Call a function - NODETYPE_METHODCALL, //!< Call a class method - NODETYPE_CREATEOBJECT, //!< Create an object - - NODETYPE_IF, //!< Conditional - NODETYPE_LOOP, //!< Looping Construct - - NODETYPE_INDEX, //!< Index into an array - - NODETYPE_LOGICALNOT, //!< Logical NOT operator - NODETYPE_LOGICALAND, //!< Logical AND operator - NODETYPE_LOGICALOR, //!< Logical OR operator - NODETYPE_LOGICALXOR, //!< Logical XOR operator - - NODETYPE_EQUALS, //!< Comparison Equals - NODETYPE_LESSTHAN, //!< Comparison Less Than - NODETYPE_LESSTHANEQUAL, //!< Comparison Less Than or Equal - NODETYPE_GREATERTHAN, //!< Comparison Greater Than - NODETYPE_GREATERTHANEQUAL, //!< Comparison Greater Than or Equal - - NODETYPE_BWNOT, //!< Bitwise NOT - NODETYPE_BWAND, //!< Bitwise AND - NODETYPE_BWOR, //!< Bitwise OR - NODETYPE_BWXOR, //!< Bitwise XOR - - NODETYPE_BITSHIFTLEFT, //!< Bitwise Shift Left (Grow) - NODETYPE_BITSHIFTRIGHT, //!< Bitwise Shift Right (Shrink) - NODETYPE_BITROTATELEFT, //!< Bitwise Rotate Left (Grow) - - NODETYPE_NEGATE, //!< Negagte - NODETYPE_ADD, //!< Add - NODETYPE_SUBTRACT, //!< Subtract - NODETYPE_MULTIPLY, //!< Multiply - NODETYPE_DIVIDE, //!< Divide - NODETYPE_MODULO, //!< Modulus -}; - -struct sAST_Node -{ - tAST_Node *NextSibling; - tAST_NodeType Type; - - const char *File; - int Line; - - void *BlockState; //!< BlockState pointer (for cache integrity) - int BlockIdent; //!< Ident (same as above) - void *ValueCache; //!< Cached value / pointer - - union - { - struct { - tAST_Node *FirstChild; - tAST_Node *LastChild; - } Block; - - struct { - int Operation; - tAST_Node *Dest; - tAST_Node *Value; - } Assign; - - struct { - tAST_Node *Value; - } UniOp; - - struct { - tAST_Node *Left; - tAST_Node *Right; - } BinOp; - - struct { - tAST_Node *Object; - tAST_Node *FirstArg; - tAST_Node *LastArg; - int NumArgs; - char Name[]; - } FunctionCall; - - struct { - tAST_Node *Condition; - tAST_Node *True; - tAST_Node *False; - } If; - - struct { - tAST_Node *Init; - int bCheckAfter; - tAST_Node *Condition; - tAST_Node *Increment; - tAST_Node *Code; - char Tag[]; - } For; - - /** - * \note Used for \a NODETYPE_VARIABLE and \a NODETYPE_CONSTANT - */ - struct { - char _unused; // Shut GCC up - char Name[]; - } Variable; - - struct { - tAST_Node *Element; - char Name[]; - } Scope; // Used by NODETYPE_SCOPE and NODETYPE_ELEMENT - - struct { - int DataType; - tAST_Node *LevelSizes; - tAST_Node *LevelSizes_Last; - tAST_Node *InitialValue; - char Name[]; - } DefVar; - - struct { - int DataType; - tAST_Node *Value; - } Cast; - - // Used for NODETYPE_REAL, NODETYPE_INTEGER and NODETYPE_STRING - tSpiderValue Constant; - }; -}; - -/** - * \brief Code Block state (stores local variables) - */ -struct sAST_BlockState -{ - tAST_BlockState *Parent; - tSpiderScript *Script; //!< Script - tAST_Variable *FirstVar; //!< First variable in the list - tSpiderValue *RetVal; - tSpiderNamespace *BaseNamespace; //!< Base namespace (for entire block) - tSpiderNamespace *CurNamespace; //!< Currently selected namespace - int Ident; //!< ID number used for variable lookup caching - const char *BreakTarget; - int BreakType; -}; - -struct sAST_Variable -{ - tAST_Variable *Next; - int Type; // Only used for static typing - tSpiderValue *Object; - char Name[]; -}; - -// === FUNCTIONS === -extern tAST_Script *AST_NewScript(void); -extern size_t AST_WriteScript(void *Buffer, tSpiderScript *Script); -extern size_t AST_WriteNode(void *Buffer, size_t Offset, tAST_Node *Node); - -extern int AST_AppendFunction(tSpiderScript *Script, const char *Name, int ReturnType, tAST_Node *FirstArg, tAST_Node *Code); - -extern tAST_Node *AST_NewNop(tParser *Parser); - -extern tAST_Node *AST_NewString(tParser *Parser, const char *String, int Length); -extern tAST_Node *AST_NewInteger(tParser *Parser, int64_t Value); -extern tAST_Node *AST_NewReal(tParser *Parser, double Value); -extern tAST_Node *AST_NewVariable(tParser *Parser, const char *Name); -extern tAST_Node *AST_NewDefineVar(tParser *Parser, int Type, const char *Name); -extern tAST_Node *AST_NewConstant(tParser *Parser, const char *Name); -extern tAST_Node *AST_NewClassElement(tParser *Parser, tAST_Node *Object, const char *Name); - -extern tAST_Node *AST_NewFunctionCall(tParser *Parser, const char *Name); -extern tAST_Node *AST_NewCreateObject(tParser *Parser, const char *Name); -extern tAST_Node *AST_NewMethodCall(tParser *Parser, tAST_Node *Object, const char *Name); -extern void AST_AppendFunctionCallArg(tAST_Node *Node, tAST_Node *Arg); - -extern tAST_Node *AST_NewCodeBlock(tParser *Parser); -extern void AST_AppendNode(tAST_Node *Parent, tAST_Node *Child); - -extern tAST_Node *AST_NewIf(tParser *Parser, tAST_Node *Condition, tAST_Node *True, tAST_Node *False); -extern tAST_Node *AST_NewLoop(tParser *Parser, const char *Tag, tAST_Node *Init, int bPostCheck, tAST_Node *Condition, tAST_Node *Increment, tAST_Node *Code); - -extern tAST_Node *AST_NewAssign(tParser *Parser, int Operation, tAST_Node *Dest, tAST_Node *Value); -extern tAST_Node *AST_NewCast(tParser *Parser, int Target, tAST_Node *Value); -extern tAST_Node *AST_NewBinOp(tParser *Parser, int Operation, tAST_Node *Left, tAST_Node *Right); -extern tAST_Node *AST_NewUniOp(tParser *Parser, int Operation, tAST_Node *Value); -extern tAST_Node *AST_NewBreakout(tParser *Parser, int Type, const char *DestTag); -extern tAST_Node *AST_NewScopeDereference(tParser *Parser, const char *Name, tAST_Node *Child); - -extern void AST_FreeNode(tAST_Node *Node); - -// exec_ast.h -extern void Object_Dereference(tSpiderValue *Object); -extern void Object_Reference(tSpiderValue *Object); -extern tSpiderValue *AST_ExecuteNode(tAST_BlockState *Block, tAST_Node *Node); -extern tSpiderValue *AST_ExecuteNode_BinOp(tSpiderScript *Script, tAST_Node *Node, int Operation, tSpiderValue *Left, tSpiderValue *Right); -extern tSpiderValue *AST_ExecuteNode_UniOp(tSpiderScript *Script, tAST_Node *Node, int Operation, tSpiderValue *Value); - -#endif diff --git a/Usermode/Libraries/libspiderscript.so_src/ast_to_bytecode.c b/Usermode/Libraries/libspiderscript.so_src/ast_to_bytecode.c deleted file mode 100644 index 58cc5f82..00000000 --- a/Usermode/Libraries/libspiderscript.so_src/ast_to_bytecode.c +++ /dev/null @@ -1,679 +0,0 @@ -/* - * SpiderScript Library - * - * AST to Bytecode Conversion - */ -#include -#include -#include -#include -#include "common.h" -#include "ast.h" -#include "bytecode_gen.h" -#include "bytecode_ops.h" - -#define TRACE_VAR_LOOKUPS 0 -#define TRACE_NODE_RETURNS 0 -#define MAX_NAMESPACE_DEPTH 10 - -// === IMPORTS === -extern tSpiderFunction *gpExports_First; - -// === TYPES === -typedef struct sAST_BlockInfo -{ - struct sAST_BlockInfo *Parent; - void *Handle; - const char *Tag; - - int BreakTarget; - int ContinueTarget; - - const char *CurNamespaceStack[MAX_NAMESPACE_DEPTH]; -} tAST_BlockInfo; - -// === PROTOTYPES === -// Node Traversal - int AST_ConvertNode(tAST_BlockInfo *Block, tAST_Node *Node, int bKeepValue); -// Variables - int BC_Variable_Define(tAST_BlockInfo *Block, int Type, const char *Name); - int BC_Variable_SetValue(tAST_BlockInfo *Block, tAST_Node *VarNode); - int BC_Variable_GetValue(tAST_BlockInfo *Block, tAST_Node *VarNode); -// - Errors -void AST_RuntimeMessage(tAST_Node *Node, const char *Type, const char *Format, ...); -void AST_RuntimeError(tAST_Node *Node, const char *Format, ...); - -// === GLOBALS === -// int giNextBlockIdent = 1; - -// === CODE === -int SpiderScript_BytecodeScript(tSpiderScript *Script) -{ - tScript_Function *fcn; - for(fcn = Script->Functions; fcn; fcn = fcn->Next) - { - if( Bytecode_ConvertFunction(fcn) == 0 ) - return -1; - } - return 0; -} - -/** - * \brief Convert a function into bytecode - */ -tBC_Function *Bytecode_ConvertFunction(tScript_Function *Fcn) -{ - tBC_Function *ret; - tAST_BlockInfo bi = {0}; - - // TODO: Return BCFcn instead? - if(Fcn->BCFcn) return Fcn->BCFcn; - - ret = Bytecode_CreateFunction(Fcn); - if(!ret) return NULL; - - bi.Handle = ret; - if( AST_ConvertNode(&bi, Fcn->ASTFcn, 0) ) - { - Bytecode_DeleteFunction(ret); - return NULL; - } - - Bytecode_AppendConstInt(ret, 0); // TODO: NULL - Bytecode_AppendReturn(ret); - Fcn->BCFcn = ret; - - return ret; -} - -// Indepotent operation -#define CHECK_IF_NEEDED(b_warn) do { if(!bKeepValue) {\ - if(b_warn)AST_RuntimeMessage(Node, "Bytecode", "Operation without saving");\ - Bytecode_AppendDelete(Block->Handle);\ -} } while(0) - -/** - * \brief Convert a node into bytecode - * \param Block Execution context - * \param Node Node to execute - */ -int AST_ConvertNode(tAST_BlockInfo *Block, tAST_Node *Node, int bKeepValue) -{ - tAST_Node *node; - int ret = 0; - int i, op = 0; - int bAddedValue = 1; // Used to tell if the value needs to be deleted - - switch(Node->Type) - { - // No Operation - case NODETYPE_NOP: - bAddedValue = 0; - break; - - // Code block - case NODETYPE_BLOCK: - Bytecode_AppendEnterContext(Block->Handle); // Create a new block - { - tAST_BlockInfo blockInfo = {0}; - blockInfo.Parent = Block; - blockInfo.Handle = Block->Handle; - // Loop over all nodes, or until the return value is set - for(node = Node->Block.FirstChild; - node; - node = node->NextSibling ) - { - AST_ConvertNode(Block, node, 0); - } - } - Bytecode_AppendLeaveContext(Block->Handle); // Leave this context - break; - - // Assignment - case NODETYPE_ASSIGN: - // TODO: Support assigning to object attributes - if( Node->Assign.Dest->Type != NODETYPE_VARIABLE ) { - AST_RuntimeError(Node, "LVALUE of assignment is not a variable"); - return -1; - } - - // Perform assignment operation - if( Node->Assign.Operation != NODETYPE_NOP ) - { - - ret = BC_Variable_GetValue(Block, Node->Assign.Dest); - if(ret) return ret; - ret = AST_ConvertNode(Block, Node->Assign.Value, 1); - if(ret) return ret; - switch(Node->Assign.Operation) - { - // General Binary Operations - case NODETYPE_ADD: op = BC_OP_ADD; break; - case NODETYPE_SUBTRACT: op = BC_OP_SUBTRACT; break; - case NODETYPE_MULTIPLY: op = BC_OP_MULTIPLY; break; - case NODETYPE_DIVIDE: op = BC_OP_DIVIDE; break; - case NODETYPE_MODULO: op = BC_OP_MODULO; break; - case NODETYPE_BWAND: op = BC_OP_BITAND; break; - case NODETYPE_BWOR: op = BC_OP_BITOR; break; - case NODETYPE_BWXOR: op = BC_OP_BITXOR; break; - case NODETYPE_BITSHIFTLEFT: op = BC_OP_BITSHIFTLEFT; break; - case NODETYPE_BITSHIFTRIGHT: op = BC_OP_BITSHIFTRIGHT; break; - case NODETYPE_BITROTATELEFT: op = BC_OP_BITROTATELEFT; break; - - default: - AST_RuntimeError(Node, "Unknown operation in ASSIGN %i", Node->Assign.Operation); - break; - } - printf("assign, op = %i\n", op); - Bytecode_AppendBinOp(Block->Handle, op); - } - else - { - ret = AST_ConvertNode(Block, Node->Assign.Value, 1); - if(ret) return ret; - } - - if( bKeepValue ) - Bytecode_AppendDuplicate(Block->Handle); - // Set the variable value - ret = BC_Variable_SetValue( Block, Node->Assign.Dest ); - break; - - // Post increment/decrement - case NODETYPE_POSTINC: - case NODETYPE_POSTDEC: - // TODO: Support assigning to object attributes - if( Node->UniOp.Value->Type != NODETYPE_VARIABLE ) { - AST_RuntimeError(Node, "LVALUE of assignment is not a variable"); - return -1; - } - - // Save original value if requested - if(bKeepValue) { - ret = BC_Variable_GetValue(Block, Node->UniOp.Value); - if(ret) return ret; - } - - Bytecode_AppendConstInt(Block->Handle, 1); - - ret = BC_Variable_GetValue(Block, Node->UniOp.Value); - if(ret) return ret; - - if( Node->Type == NODETYPE_POSTDEC ) - Bytecode_AppendBinOp(Block->Handle, BC_OP_SUBTRACT); - else - Bytecode_AppendBinOp(Block->Handle, BC_OP_ADD); - if(ret) return ret; - - - ret = BC_Variable_SetValue(Block, Node->UniOp.Value); - if(ret) return ret; - // Doesn't push unless needed - break; - - // Function Call - case NODETYPE_METHODCALL: - case NODETYPE_FUNCTIONCALL: - case NODETYPE_CREATEOBJECT: { - int nargs = 0; - - // Put the object earlier on the stack to the arguments (for exec) - if( Node->Type == NODETYPE_METHODCALL ) { - ret = AST_ConvertNode(Block, Node->FunctionCall.Object, 1); - if(ret) return ret; - } - - for(node = Node->FunctionCall.FirstArg; node; node = node->NextSibling) - { - ret = AST_ConvertNode(Block, node, 1); - if(ret) return ret; - nargs ++; - } - - // Call the function - if( Node->Type == NODETYPE_METHODCALL ) - { - // TODO: Sanity check stack top - Bytecode_AppendMethodCall(Block->Handle, Node->FunctionCall.Name, nargs); - } - else - { - int newnamelen = 0; - char *manglename; - for( i = 0; i < MAX_NAMESPACE_DEPTH && Block->CurNamespaceStack[i]; i ++ ) - newnamelen = strlen(Block->CurNamespaceStack[i]) + 1; - newnamelen += strlen(Node->FunctionCall.Name) + 1; - manglename = alloca(newnamelen); - manglename[0] = 0; - for( i = 0; i < MAX_NAMESPACE_DEPTH && Block->CurNamespaceStack[i]; i ++ ) { - int pos; - strcat(manglename, Block->CurNamespaceStack[i]); - pos = strlen(manglename); - manglename[pos] = BC_NS_SEPARATOR; - manglename[pos+1] = '\0'; - } - strcat(manglename, Node->FunctionCall.Name); - - if( Node->Type == NODETYPE_CREATEOBJECT ) - { - // TODO: Sanity check stack top - Bytecode_AppendCreateObj(Block->Handle, manglename, nargs); - } - else - { - Bytecode_AppendFunctionCall(Block->Handle, manglename, nargs); - } - } - CHECK_IF_NEEDED(0); // Don't warn - // TODO: Implement warn_unused_ret - } break; - - // Conditional - case NODETYPE_IF: { - int if_end; - ret = AST_ConvertNode(Block, Node->If.Condition, 1); - if(ret) return ret; - - if_end = Bytecode_AllocateLabel(Block->Handle); - - if( Node->If.False->Type != NODETYPE_NOP ) - { - int if_true = Bytecode_AllocateLabel(Block->Handle); - - Bytecode_AppendCondJump(Block->Handle, if_true); - - // False - ret = AST_ConvertNode(Block, Node->If.False, 0); - if(ret) return ret; - Bytecode_AppendJump(Block->Handle, if_end); - Bytecode_SetLabel(Block->Handle, if_true); - } - else - { - Bytecode_AppendCondJumpNot(Block->Handle, if_end); - } - - // True - ret = AST_ConvertNode(Block, Node->If.True, 0); - if(ret) return ret; - - // End - Bytecode_SetLabel(Block->Handle, if_end); - } break; - - // Loop - case NODETYPE_LOOP: { - int loop_start, loop_end; - int saved_break, saved_continue; - const char *saved_tag; - - // Initialise - ret = AST_ConvertNode(Block, Node->For.Init, 0); - if(ret) return ret; - - loop_start = Bytecode_AllocateLabel(Block->Handle); - loop_end = Bytecode_AllocateLabel(Block->Handle); - - saved_break = Block->BreakTarget; - saved_continue = Block->ContinueTarget; - saved_tag = Block->Tag; - Block->BreakTarget = loop_end; - Block->ContinueTarget = loop_end; - Block->Tag = Node->For.Tag; - - Bytecode_SetLabel(Block->Handle, loop_start); - - // Check initial condition - if( !Node->For.bCheckAfter ) - { - ret = AST_ConvertNode(Block, Node->For.Condition, 1); - if(ret) return ret; - Bytecode_AppendUniOp(Block->Handle, BC_OP_LOGICNOT); - Bytecode_AppendCondJump(Block->Handle, loop_end); - } - - // Code - ret = AST_ConvertNode(Block, Node->For.Code, 0); - if(ret) return ret; - - // Increment - ret = AST_ConvertNode(Block, Node->For.Increment, 0); - if(ret) return ret; - - // Tail check - if( Node->For.bCheckAfter ) - { - ret = AST_ConvertNode(Block, Node->For.Condition, 1); - if(ret) return ret; - Bytecode_AppendCondJump(Block->Handle, loop_start); - } - else - { - Bytecode_AppendJump(Block->Handle, loop_start); - } - - Bytecode_SetLabel(Block->Handle, loop_end); - - Block->BreakTarget = saved_break; - Block->ContinueTarget = saved_continue; - Block->Tag = saved_tag; - } break; - - // Return - case NODETYPE_RETURN: - ret = AST_ConvertNode(Block, Node->UniOp.Value, 1); - if(ret) return ret; - Bytecode_AppendReturn(Block->Handle); - break; - - case NODETYPE_BREAK: - case NODETYPE_CONTINUE: { - tAST_BlockInfo *bi = Block; - if( Node->Variable.Name[0] ) { - while(bi && strcmp(bi->Tag, Node->Variable.Name) == 0) bi = bi->Parent; - } - if( !bi ) return 1; - // TODO: Check if BreakTarget/ContinueTarget are valid - if( Node->Type == NODETYPE_BREAK ) - Bytecode_AppendJump(Block->Handle, bi->BreakTarget); - else - Bytecode_AppendJump(Block->Handle, bi->ContinueTarget); - } break; - - // Define a variable - case NODETYPE_DEFVAR: - ret = BC_Variable_Define(Block, Node->DefVar.DataType, Node->DefVar.Name); - if(ret) return ret; - - if( Node->DefVar.InitialValue ) - { - ret = AST_ConvertNode(Block, Node->DefVar.InitialValue, 1); - if(ret) return ret; - Bytecode_AppendSaveVar(Block->Handle, Node->DefVar.Name); - } - break; - - // Scope - case NODETYPE_SCOPE: - for( i = 0; i < MAX_NAMESPACE_DEPTH && Block->CurNamespaceStack[i]; i ++ ); - if( i == MAX_NAMESPACE_DEPTH ) { - AST_RuntimeError(Node, "Exceeded max explicit namespace depth (%i)", i); - return 2; - } - Block->CurNamespaceStack[i] = Node->Scope.Name; - ret = AST_ConvertNode(Block, Node->Scope.Element, 2); - Block->CurNamespaceStack[i] = NULL; - CHECK_IF_NEEDED(0); // No warning? - // TODO: Will this collide with _CALLFUNCTION etc? - break; - - // Variable - case NODETYPE_VARIABLE: - ret = BC_Variable_GetValue( Block, Node ); - CHECK_IF_NEEDED(1); - break; - - // Element of an Object - case NODETYPE_ELEMENT: - ret = AST_ConvertNode( Block, Node->Scope.Element, 1 ); - if(ret) return ret; - - Bytecode_AppendElement(Block->Handle, Node->Scope.Name); - CHECK_IF_NEEDED(1); - break; - - // Cast a value to another - case NODETYPE_CAST: - ret = AST_ConvertNode(Block, Node->Cast.Value, 1); - if(ret) return ret; - Bytecode_AppendCast(Block->Handle, Node->Cast.DataType); - CHECK_IF_NEEDED(1); - break; - - // Index into an array - case NODETYPE_INDEX: - ret = AST_ConvertNode(Block, Node->BinOp.Left, 1); // Array - if(ret) return ret; - ret = AST_ConvertNode(Block, Node->BinOp.Right, 1); // Offset - if(ret) return ret; - - Bytecode_AppendIndex(Block->Handle); - CHECK_IF_NEEDED(1); - break; - - // TODO: Implement runtime constants - case NODETYPE_CONSTANT: - // TODO: Scan namespace for constant name - AST_RuntimeError(Node, "TODO - Runtime Constants"); - ret = -1; - break; - - // Constant Values - case NODETYPE_STRING: - Bytecode_AppendConstString(Block->Handle, Node->Constant.String.Data, Node->Constant.String.Length); - CHECK_IF_NEEDED(1); - break; - case NODETYPE_INTEGER: - Bytecode_AppendConstInt(Block->Handle, Node->Constant.Integer); - CHECK_IF_NEEDED(1); - break; - case NODETYPE_REAL: - Bytecode_AppendConstReal(Block->Handle, Node->Constant.Real); - CHECK_IF_NEEDED(1); - break; - - // --- Operations --- - // Boolean Operations - case NODETYPE_LOGICALNOT: // Logical NOT (!) - if(!op) op = BC_OP_LOGICNOT; - case NODETYPE_BWNOT: // Bitwise NOT (~) - if(!op) op = BC_OP_BITNOT; - case NODETYPE_NEGATE: // Negation (-) - if(!op) op = BC_OP_NEG; - ret = AST_ConvertNode(Block, Node->UniOp.Value, 1); - if(ret) return ret; - Bytecode_AppendUniOp(Block->Handle, op); - CHECK_IF_NEEDED(1); - break; - - // Logic - case NODETYPE_LOGICALAND: if(!op) op = BC_OP_LOGICAND; - case NODETYPE_LOGICALOR: if(!op) op = BC_OP_LOGICOR; - case NODETYPE_LOGICALXOR: if(!op) op = BC_OP_LOGICXOR; - // Comparisons - case NODETYPE_EQUALS: if(!op) op = BC_OP_EQUALS; - case NODETYPE_LESSTHAN: if(!op) op = BC_OP_LESSTHAN; - case NODETYPE_GREATERTHAN: if(!op) op = BC_OP_GREATERTHAN; - case NODETYPE_LESSTHANEQUAL: if(!op) op = BC_OP_LESSTHANOREQUAL; - case NODETYPE_GREATERTHANEQUAL: if(!op) op = BC_OP_GREATERTHANOREQUAL; - // General Binary Operations - case NODETYPE_ADD: if(!op) op = BC_OP_ADD; - case NODETYPE_SUBTRACT: if(!op) op = BC_OP_SUBTRACT; - case NODETYPE_MULTIPLY: if(!op) op = BC_OP_MULTIPLY; - case NODETYPE_DIVIDE: if(!op) op = BC_OP_DIVIDE; - case NODETYPE_MODULO: if(!op) op = BC_OP_MODULO; - case NODETYPE_BWAND: if(!op) op = BC_OP_BITAND; - case NODETYPE_BWOR: if(!op) op = BC_OP_BITOR; - case NODETYPE_BWXOR: if(!op) op = BC_OP_BITXOR; - case NODETYPE_BITSHIFTLEFT: if(!op) op = BC_OP_BITSHIFTLEFT; - case NODETYPE_BITSHIFTRIGHT: if(!op) op = BC_OP_BITSHIFTRIGHT; - case NODETYPE_BITROTATELEFT: if(!op) op = BC_OP_BITROTATELEFT; - ret = AST_ConvertNode(Block, Node->BinOp.Left, 1); - if(ret) return ret; - ret = AST_ConvertNode(Block, Node->BinOp.Right, 1); - if(ret) return ret; - - Bytecode_AppendBinOp(Block->Handle, op); - CHECK_IF_NEEDED(1); - break; - - default: - ret = -1; - AST_RuntimeError(Node, "BUG - SpiderScript AST_ConvertNode Unimplemented %i", Node->Type); - break; - } - - #if TRACE_NODE_RETURNS - if(ret && ret != ERRPTR) { - AST_RuntimeError(Node, "Ret type of %p %i is %i", Node, Node->Type, ret->Type); - } - else { - AST_RuntimeError(Node, "Ret type of %p %i is %p", Node, Node->Type, ret); - } - #endif - - return ret; -} - -/** - * \brief Define a variable - * \param Block Current block state - * \param Type Type of the variable - * \param Name Name of the variable - * \return Boolean Failure - */ -int BC_Variable_Define(tAST_BlockInfo *Block, int Type, const char *Name) -{ - #if 0 - tAST_Variable *var, *prev = NULL; - - for( var = Block->FirstVar; var; prev = var, var = var->Next ) - { - if( strcmp(var->Name, Name) == 0 ) { - AST_RuntimeError(NULL, "Redefinition of variable '%s'", Name); - return ERRPTR; - } - } - - var = malloc( sizeof(tAST_Variable) + strlen(Name) + 1 ); - var->Next = NULL; - var->Type = Type; - strcpy(var->Name, Name); - - if(prev) prev->Next = var; - else Block->FirstVar = var; - - return var; - #else - Bytecode_AppendDefineVar(Block->Handle, Name, Type); - return 0; - #endif -} - -tAST_Variable *BC_Variable_Lookup(tAST_BlockInfo *Block, tAST_Node *VarNode, int CreateType) -{ - #if 0 - tAST_Variable *var = NULL; - - // Speed hack - if( VarNode->BlockState == Block && VarNode->BlockIdent == Block->Ident ) { - var = VarNode->ValueCache; - #if TRACE_VAR_LOOKUPS - AST_RuntimeMessage(VarNode, "debug", "Fast var fetch on '%s' %p (%p:%i)", - VarNode->Variable.Name, var, - VarNode->BlockState, VarNode->BlockIdent - ); - #endif - } - else - { - tAST_BlockInfo *bs; - for( bs = Block; bs; bs = bs->Parent ) - { - for( var = bs->FirstVar; var; var = var->Next ) - { - if( strcmp(var->Name, VarNode->Variable.Name) == 0 ) - break; - } - if(var) break; - } - - if( !var ) - { - if( Block->Script->Variant->bDyamicTyped && CreateType != SS_DATATYPE_UNDEF ) { - // Define variable - var = BC_Variable_Define(Block, CreateType, VarNode->Variable.Name, NULL); - } - else - { - AST_RuntimeError(VarNode, "Variable '%s' is undefined", VarNode->Variable.Name); - return NULL; - } - } - - #if TRACE_VAR_LOOKUPS - AST_RuntimeMessage(VarNode, "debug", "Saved variable lookup of '%s' %p (%p:%i)", - VarNode->Variable.Name, var, - Block, Block->Ident); - #endif - - VarNode->ValueCache = var; - VarNode->BlockState = Block; - VarNode->BlockIdent = Block->Ident; - } - - return var; - #else - return (void*)1; - #endif -} - -/** - * \brief Set the value of a variable - * \return Boolean Failure - */ -int BC_Variable_SetValue(tAST_BlockInfo *Block, tAST_Node *VarNode) -{ - tAST_Variable *var; - - var = BC_Variable_Lookup(Block, VarNode, SS_DATATYPE_UNDEF); - if(!var) return -1; - - // TODO: Check types - - Bytecode_AppendSaveVar(Block->Handle, VarNode->Variable.Name); - return 0; -} - -/** - * \brief Get the value of a variable - */ -int BC_Variable_GetValue(tAST_BlockInfo *Block, tAST_Node *VarNode) -{ - tAST_Variable *var; - - var = BC_Variable_Lookup(Block, VarNode, 0); - if(!var) return -1; - - Bytecode_AppendLoadVar(Block->Handle, VarNode->Variable.Name); - return 0; -} - -#if 0 -void AST_RuntimeMessage(tAST_Node *Node, const char *Type, const char *Format, ...) -{ - va_list args; - - if(Node) { - fprintf(stderr, "%s:%i: ", Node->File, Node->Line); - } - fprintf(stderr, "%s: ", Type); - va_start(args, Format); - vfprintf(stderr, Format, args); - va_end(args); - fprintf(stderr, "\n"); -} -void AST_RuntimeError(tAST_Node *Node, const char *Format, ...) -{ - va_list args; - - if(Node) { - fprintf(stderr, "%s:%i: ", Node->File, Node->Line); - } - fprintf(stderr, "error: "); - va_start(args, Format); - vfprintf(stderr, Format, args); - va_end(args); - fprintf(stderr, "\n"); -} -#endif diff --git a/Usermode/Libraries/libspiderscript.so_src/bytecode.h b/Usermode/Libraries/libspiderscript.so_src/bytecode.h deleted file mode 100644 index bc3c91cd..00000000 --- a/Usermode/Libraries/libspiderscript.so_src/bytecode.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - * SpiderScript - * - Bytecode definitions - */ -#ifndef _BYTECODE_H_ -#define _BYTECODE_H_ - -#include "bytecode_ops.h" - -#define BC_NS_SEPARATOR '@' - -typedef struct sBC_Op tBC_Op; -typedef struct sBC_Function tBC_Function; - -struct sBC_Op -{ - tBC_Op *Next; - int Operation; - char bUseInteger; // Used for serialisation - char bUseString; // Used for serialisation - union { - struct { - int Integer; - char String[]; - } StringInt; - - uint64_t Integer; - double Real; - } Content; -}; - -struct sBC_Function -{ - int LabelCount; - int LabelSpace; - tBC_Op **Labels; - - int MaxVariableCount; - // NOTE: These fields are invalid after compilation - int VariableCount; - int VariableSpace; - const char **VariableNames; - int CurContextDepth; // Used to get the real var count - - int OperationCount; - tBC_Op *Operations; - tBC_Op *OperationsEnd; -}; - -#endif diff --git a/Usermode/Libraries/libspiderscript.so_src/bytecode_gen.c b/Usermode/Libraries/libspiderscript.so_src/bytecode_gen.c deleted file mode 100644 index b089b9ae..00000000 --- a/Usermode/Libraries/libspiderscript.so_src/bytecode_gen.c +++ /dev/null @@ -1,444 +0,0 @@ -/* - * SpiderScript Library - * by John Hodge (thePowersGang) - * - * bytecode_gen.c - * - Generate bytecode - */ -#include -#include -#include "bytecode_ops.h" -#include -#include "bytecode_gen.h" -#include -#include "bytecode.h" - -// === IMPORTS === - -// === STRUCTURES === - -// === PROTOTYPES === -tBC_Op *Bytecode_int_AllocateOp(int Operation, int ExtraBytes); - int Bytecode_int_AddVariable(tBC_Function *Handle, const char *Name); - -// === GLOBALS === - -// === CODE === -tBC_Op *Bytecode_int_AllocateOp(int Operation, int ExtraBytes) -{ - tBC_Op *ret; - - ret = malloc(sizeof(tBC_Op) + ExtraBytes); - if(!ret) return NULL; - - ret->Next = NULL; - ret->Operation = Operation; - ret->bUseInteger = 0; - ret->bUseString = (ExtraBytes > 0); - - return ret; -} - -tBC_Function *Bytecode_CreateFunction(tScript_Function *Fcn) -{ - tBC_Function *ret; - int i; - - ret = malloc(sizeof(tBC_Function)); - if(!ret) return NULL; - - ret->LabelSpace = ret->LabelCount = 0; - ret->Labels = NULL; - - ret->MaxVariableCount = 0; - ret->CurContextDepth = 0; - ret->VariableCount = ret->VariableSpace = 0; - ret->VariableNames = NULL; - - ret->OperationCount = 0; - ret->Operations = NULL; - ret->OperationsEnd = (void*)&ret->Operations; - - for( i = 0; i < Fcn->ArgumentCount; i ++ ) - { - Bytecode_int_AddVariable(ret, Fcn->Arguments[i].Name); - } - - return ret; -} - -void Bytecode_DeleteFunction(tBC_Function *Fcn) -{ - tBC_Op *op; - for( op = Fcn->Operations; op; ) - { - tBC_Op *nextop = op->Next; - free(op); - op = nextop; - } - free(Fcn->VariableNames); - free(Fcn->Labels); - free(Fcn); -} - -int StringList_GetString(tStringList *List, const char *String, int Length) -{ - int strIdx = 0; - tString *ent; - for(ent = List->Head; ent; ent = ent->Next, strIdx ++) - { - if(ent->Length == Length && memcmp(ent->Data, String, Length) == 0) break; - } - if( ent ) { - ent->RefCount ++; - } - else { - ent = malloc(sizeof(tString) + Length + 1); - if(!ent) return -1; - ent->Next = NULL; - ent->Length = Length; - ent->RefCount = 1; - memcpy(ent->Data, String, Length); - ent->Data[Length] = '\0'; - - if(List->Head) - List->Tail->Next = ent; - else - List->Head = ent; - List->Tail = ent; - List->Count ++; - } - return strIdx; -} - -int Bytecode_int_Serialize(const tBC_Function *Function, void *Output, int *LabelOffsets, tStringList *Strings) -{ - tBC_Op *op; - int len = 0, idx = 0; - int i; - - void _put_byte(uint8_t byte) - { - uint8_t *buf = Output; - if(Output) buf[len] = byte; - len ++; - } - - void _put_dword(uint32_t value) - { - uint8_t *buf = Output; - if(Output) { - buf[len+0] = value & 0xFF; - buf[len+1] = value >> 8; - buf[len+2] = value >> 16; - buf[len+3] = value >> 24; - } - len += 4; - } - - void _put_qword(uint64_t value) - { - _put_dword(value & 0xFFFFFFFF); - _put_dword(value >> 32); - } - - void _put_double(double value) - { - // TODO: Machine agnostic - if(Output) { - *(double*)( (char*)Output + len ) = value; - } - len += sizeof(double); - } - - void _put_string(const char *str, int len) - { - int strIdx = 0; - if( Output ) { - strIdx = StringList_GetString(Strings, str, len); - } - - // TODO: Relocations - _put_dword(strIdx); - } - - for( op = Function->Operations; op; op = op->Next, idx ++ ) - { - // If first run, convert labels into byte offsets - if( !Output ) - { - for( i = 0; i < Function->LabelCount; i ++ ) - { - if(LabelOffsets[i]) continue; - if(op != Function->Labels[i]) continue; - - LabelOffsets[i] = len; - } - } - - _put_byte(op->Operation); - switch(op->Operation) - { - // Relocate jumps (the value only matters if `Output` is non-NULL) - case BC_OP_JUMP: - case BC_OP_JUMPIF: - case BC_OP_JUMPIFNOT: - // TODO: Relocations? - _put_dword( LabelOffsets[op->Content.StringInt.Integer] ); - break; - // Special case for inline values - case BC_OP_LOADINT: - _put_qword(op->Content.Integer); - break; - case BC_OP_LOADREAL: - _put_double(op->Content.Real); - break; - case BC_OP_LOADSTR: - _put_string(op->Content.StringInt.String, op->Content.StringInt.Integer); - break; - // Everthing else just gets handled nicely - default: - if( op->bUseString ) - _put_string(op->Content.StringInt.String, strlen(op->Content.StringInt.String)); - if( op->bUseInteger ) - _put_dword(op->Content.StringInt.Integer); - break; - } - } - - return len; -} - -char *Bytecode_SerialiseFunction(const tBC_Function *Function, int *Length, tStringList *Strings) -{ - int len; - int *label_offsets; - char *code; - - label_offsets = calloc( sizeof(int), Function->LabelCount ); - if(!label_offsets) return NULL; - - len = Bytecode_int_Serialize(Function, NULL, label_offsets, Strings); - - code = malloc(len); - - Bytecode_int_Serialize(Function, code, label_offsets, Strings); - - free(label_offsets); - - *Length = len; - - return code; -} - -int Bytecode_AllocateLabel(tBC_Function *Handle) -{ - int ret; - - if( Handle->LabelCount == Handle->LabelSpace ) { - void *tmp; - Handle->LabelSpace += 20; // TODO: Don't hardcode increment - tmp = realloc(Handle->Labels, Handle->LabelSpace * sizeof(Handle->Labels[0])); - if( !tmp ) { - Handle->LabelSpace -= 20; - return -1; - } - Handle->Labels = tmp; - } - ret = Handle->LabelCount ++; - Handle->Labels[ret] = 0; - return ret; -} - -void Bytecode_SetLabel(tBC_Function *Handle, int Label) -{ - if(Label < 0) return ; - - if(Label >= Handle->LabelCount) return ; - - Handle->Labels[Label] = Handle->OperationsEnd; - return ; -} - -void Bytecode_int_AppendOp(tBC_Function *Fcn, tBC_Op *Op) -{ - Op->Next = NULL; - if( Fcn->Operations ) - Fcn->OperationsEnd->Next = Op; - else - Fcn->Operations = Op; - Fcn->OperationsEnd = Op; -} - -int Bytecode_int_AddVariable(tBC_Function *Handle, const char *Name) -{ - if(Handle->VariableCount == Handle->VariableSpace) { - void *tmp; - Handle->VariableSpace += 10; - tmp = realloc(Handle->VariableNames, Handle->VariableSpace * sizeof(Handle->VariableNames[0])); - if(!tmp) return -1; // TODO: Error - Handle->VariableNames = tmp; - } - Handle->VariableNames[Handle->VariableCount] = Name; - Handle->VariableCount ++; - // Get max count (used when executing to get the frame size) - if(Handle->VariableCount - Handle->CurContextDepth >= Handle->MaxVariableCount) - Handle->MaxVariableCount = Handle->VariableCount - Handle->CurContextDepth; -// printf("_AddVariable: %s given %i\n", Name, Handle->VariableCount - Handle->CurContextDepth - 1); - return Handle->VariableCount - Handle->CurContextDepth - 1; -} - -int Bytecode_int_GetVarIndex(tBC_Function *Handle, const char *Name) -{ - int i, context_depth = Handle->CurContextDepth; - // Get the start of this context - for( i = Handle->VariableCount; i --; ) - { - if( !Handle->VariableNames[i] ) { - context_depth --; - continue ; - } - if( strcmp(Name, Handle->VariableNames[i]) == 0 ) - return i - context_depth; - } - return -1; -} - -#define DEF_BC_NONE(_op) { \ - tBC_Op *op = Bytecode_int_AllocateOp(_op, 0); \ - op->Content.Integer = 0; \ - op->bUseInteger = 0; \ - Bytecode_int_AppendOp(Handle, op);\ -} - -#define DEF_BC_INT(_op, _int) {\ - tBC_Op *op = Bytecode_int_AllocateOp(_op, 0);\ - op->Content.StringInt.Integer = _int;\ - op->bUseInteger = 1;\ - op->bUseString = 0;\ - Bytecode_int_AppendOp(Handle, op);\ -} - -#define DEF_BC_STRINT(_op, _str, _int) { \ - tBC_Op *op = Bytecode_int_AllocateOp(_op, strlen(_str));\ - op->Content.StringInt.Integer = _int;\ - strcpy(op->Content.StringInt.String, _str);\ - op->bUseInteger = 1;\ - op->bUseString = 1;\ - Bytecode_int_AppendOp(Handle, op);\ -} -#define DEF_BC_STR(_op, _str) {\ - tBC_Op *op = Bytecode_int_AllocateOp(_op, strlen(_str));\ - strcpy(op->Content.StringInt.String, _str);\ - op->bUseInteger = 0;\ - Bytecode_int_AppendOp(Handle, op);\ -} - -// --- Flow Control -void Bytecode_AppendJump(tBC_Function *Handle, int Label) - DEF_BC_INT(BC_OP_JUMP, Label) -void Bytecode_AppendCondJump(tBC_Function *Handle, int Label) - DEF_BC_INT(BC_OP_JUMPIF, Label) -void Bytecode_AppendCondJumpNot(tBC_Function *Handle, int Label) - DEF_BC_INT(BC_OP_JUMPIFNOT, Label) -void Bytecode_AppendReturn(tBC_Function *Handle) - DEF_BC_NONE(BC_OP_RETURN); - -// --- Variables -void Bytecode_AppendLoadVar(tBC_Function *Handle, const char *Name) - DEF_BC_INT(BC_OP_LOADVAR, Bytecode_int_GetVarIndex(Handle, Name)) -// DEF_BC_STR(BC_OP_LOADVAR, Name) -void Bytecode_AppendSaveVar(tBC_Function *Handle, const char *Name) // (Obj->)?var = - DEF_BC_INT(BC_OP_SAVEVAR, Bytecode_int_GetVarIndex(Handle, Name)) -// DEF_BC_STR(BC_OP_SAVEVAR, Name) - -// --- Constants -void Bytecode_AppendConstInt(tBC_Function *Handle, uint64_t Value) -{ - tBC_Op *op = Bytecode_int_AllocateOp(BC_OP_LOADINT, 0); - op->Content.Integer = Value; - Bytecode_int_AppendOp(Handle, op); -} -void Bytecode_AppendConstReal(tBC_Function *Handle, double Value) -{ - tBC_Op *op = Bytecode_int_AllocateOp(BC_OP_LOADREAL, 0); - op->Content.Real = Value; - Bytecode_int_AppendOp(Handle, op); -} -void Bytecode_AppendConstString(tBC_Function *Handle, const void *Data, size_t Length) -{ - tBC_Op *op = Bytecode_int_AllocateOp(BC_OP_LOADSTR, Length+1); - op->Content.StringInt.Integer = Length; - memcpy(op->Content.StringInt.String, Data, Length); - op->Content.StringInt.String[Length] = 0; - Bytecode_int_AppendOp(Handle, op); -} - -// --- Indexing / Scoping -void Bytecode_AppendElement(tBC_Function *Handle, const char *Name) - DEF_BC_STR(BC_OP_ELEMENT, Name) -void Bytecode_AppendIndex(tBC_Function *Handle) - DEF_BC_NONE(BC_OP_INDEX) - -void Bytecode_AppendCreateObj(tBC_Function *Handle, const char *Name, int ArgumentCount) - DEF_BC_STRINT(BC_OP_CREATEOBJ, Name, ArgumentCount) -void Bytecode_AppendMethodCall(tBC_Function *Handle, const char *Name, int ArgumentCount) - DEF_BC_STRINT(BC_OP_CALLMETHOD, Name, ArgumentCount) -void Bytecode_AppendFunctionCall(tBC_Function *Handle, const char *Name, int ArgumentCount) - DEF_BC_STRINT(BC_OP_CALLFUNCTION, Name, ArgumentCount) - -void Bytecode_AppendBinOp(tBC_Function *Handle, int Operation) - DEF_BC_NONE(Operation) -void Bytecode_AppendUniOp(tBC_Function *Handle, int Operation) - DEF_BC_NONE(Operation) -void Bytecode_AppendCast(tBC_Function *Handle, int Type) - DEF_BC_INT(BC_OP_CAST, Type) -void Bytecode_AppendDuplicate(tBC_Function *Handle) - DEF_BC_NONE(BC_OP_DUPSTACK); -void Bytecode_AppendDelete(tBC_Function *Handle) - DEF_BC_NONE(BC_OP_DELSTACK); - -// Does some bookeeping to allocate variable slots at compile time -void Bytecode_AppendEnterContext(tBC_Function *Handle) -{ - Handle->CurContextDepth ++; - Bytecode_int_AddVariable(Handle, NULL); // NULL to record the extent of this - - DEF_BC_NONE(BC_OP_ENTERCONTEXT) -} -void Bytecode_AppendLeaveContext(tBC_Function *Handle) -{ - int i; - for( i = Handle->VariableCount; i --; ) - { - if( Handle->VariableNames[i] == NULL ) break; - } - Handle->CurContextDepth --; - Handle->VariableCount = i; - - DEF_BC_NONE(BC_OP_LEAVECONTEXT); -} -//void Bytecode_AppendImportNamespace(tBC_Function *Handle, const char *Name); -// DEF_BC_STRINT(BC_OP_IMPORTNS, Name, 0) -void Bytecode_AppendDefineVar(tBC_Function *Handle, const char *Name, int Type) -{ - int i; - #if 1 - // Get the start of this context - for( i = Handle->VariableCount; i --; ) - { - if( Handle->VariableNames[i] == NULL ) break; - } - // Check for duplicate allocation - for( i ++; i < Handle->VariableCount; i ++ ) - { - if( strcmp(Name, Handle->VariableNames[i]) == 0 ) - return ; - } - #endif - - i = Bytecode_int_AddVariable(Handle, Name); -// printf("Variable %s given slot %i\n", Name, i); - - DEF_BC_STRINT(BC_OP_DEFINEVAR, Name, (Type&0xFFFF) | (i << 16)) -} diff --git a/Usermode/Libraries/libspiderscript.so_src/bytecode_gen.h b/Usermode/Libraries/libspiderscript.so_src/bytecode_gen.h deleted file mode 100644 index 0d901ebd..00000000 --- a/Usermode/Libraries/libspiderscript.so_src/bytecode_gen.h +++ /dev/null @@ -1,79 +0,0 @@ -/* - * SpiderScript Library - * - By John Hodge (thePowersGang) - * - * bytecode_gen.h - * - Bytecode Generation header - */ -#ifndef _BYTECODE_GEN_H_ -#define _BYTECODE_GEN_H_ - -#include "common.h" -#include "ast.h" -#include "bytecode.h" - -typedef struct sStringList tStringList; -typedef struct sString tString; - -struct sString -{ - tString *Next; - int Length; - int RefCount; - char Data[]; -}; - -struct sStringList -{ - tString *Head; - tString *Tail; - int Count; -}; - - -extern int Bytecode_ConvertScript(tSpiderScript *Script, const char *DestFile); -extern tBC_Function *Bytecode_ConvertFunction(tScript_Function *Fcn); -extern tBC_Function *Bytecode_NewBlankFunction(void); -extern void Bytecode_DeleteFunction(tBC_Function *Fcn); - -extern char *Bytecode_SerialiseFunction(const tBC_Function *Function, int *Length, tStringList *Strings); -extern int StringList_GetString(tStringList *List, const char *String, int Length); -extern tBC_Function *Bytecode_CreateFunction(tScript_Function *Fcn); - -extern int Bytecode_AllocateLabel(tBC_Function *Handle); -extern void Bytecode_SetLabel(tBC_Function *Handle, int Label); -// Bytecode adding -// - Flow Control -extern void Bytecode_AppendJump(tBC_Function *Handle, int Label); -extern void Bytecode_AppendCondJump(tBC_Function *Handle, int Label); -extern void Bytecode_AppendCondJumpNot(tBC_Function *Handle, int Label); -extern void Bytecode_AppendReturn(tBC_Function *Handle); -// - Operation Stack -// > Load/Store -extern void Bytecode_AppendLoadVar(tBC_Function *Handle, const char *Name); -extern void Bytecode_AppendSaveVar(tBC_Function *Handle, const char *Name); // (Obj->)?var = -extern void Bytecode_AppendConstInt(tBC_Function *Handle, uint64_t Value); -extern void Bytecode_AppendConstReal(tBC_Function *Handle, double Value); -extern void Bytecode_AppendConstString(tBC_Function *Handle, const void *Data, size_t Length); -// > Scoping -extern void Bytecode_AppendElement(tBC_Function *Handle, const char *Name); // Obj->SubObj -extern void Bytecode_AppendIndex(tBC_Function *Handle); // Index into an array -// > Function Calls -extern void Bytecode_AppendCreateObj(tBC_Function *Handle, const char *Name, int ArgumentCount); -extern void Bytecode_AppendMethodCall(tBC_Function *Handle, const char *Name, int ArgumentCount); -extern void Bytecode_AppendFunctionCall(tBC_Function *Handle, const char *Name, int ArgumentCount); -// > Manipulation -extern void Bytecode_AppendBinOp(tBC_Function *Handle, int Operation); -extern void Bytecode_AppendUniOp(tBC_Function *Handle, int Operation); -extern void Bytecode_AppendCast(tBC_Function *Handlde, int Type); -extern void Bytecode_AppendDuplicate(tBC_Function *Handlde); -extern void Bytecode_AppendDelete(tBC_Function *Handle); -// - Context -// TODO: Are contexts needed? Should variables be allocated like labels? -extern void Bytecode_AppendEnterContext(tBC_Function *Handle); -extern void Bytecode_AppendLeaveContext(tBC_Function *Handle); -//extern void Bytecode_AppendImportNamespace(tBC_Function *Handle, const char *Name); -extern void Bytecode_AppendDefineVar(tBC_Function *Handle, const char *Name, int Type); - -#endif - diff --git a/Usermode/Libraries/libspiderscript.so_src/bytecode_makefile.c b/Usermode/Libraries/libspiderscript.so_src/bytecode_makefile.c deleted file mode 100644 index 5affbef0..00000000 --- a/Usermode/Libraries/libspiderscript.so_src/bytecode_makefile.c +++ /dev/null @@ -1,133 +0,0 @@ -/* - * SpiderScript Library - * by John Hodge (thePowersGang) - * - * bytecode_makefile.c - * - Generate a bytecode file - */ -#include -#include "ast.h" -#include "bytecode_gen.h" -#include -#include - -// === IMPORTS === - -// === PROTOTYPES === - -// === GLOBALS === - -// === CODE === -int SpiderScript_SaveBytecode(tSpiderScript *Script, const char *DestFile) -{ - tStringList strings = {0}; - tScript_Function *fcn; - FILE *fp; - int fcn_hdr_offset = 0; - int fcn_count = 0; - int strtab_ofs; - int i; - - void _put8(uint8_t val) - { - fwrite(&val, 1, 1, fp); - } - void _put32(uint32_t val) - { - _put8(val & 0xFF); - _put8(val >> 8); - _put8(val >> 16); - _put8(val >> 24); - } - - fp = fopen(DestFile, "wb"); - if(!fp) return 1; - - // Create header - fwrite("SSBC\r\n\xBC\x55", 8, 1, fp); - _put32(0); // Function count, to be filled - _put32(0); // String count - _put32(0); // String table offset - // TODO: Variant info - - fcn_hdr_offset = ftell(fp); - - // Create function descriptors - for(fcn = Script->Functions; fcn; fcn = fcn->Next, fcn_count ++) - { - _put32( StringList_GetString(&strings, fcn->Name, strlen(fcn->Name)) ); - _put32( 0 ); // Code offset - // TODO: Namespace - _put8( fcn->ReturnType ); - - if(fcn->ArgumentCount > 255) { - // ERROR: Too many args - return 2; - } - _put8( fcn->ArgumentCount ); - - // Argument types? - for( i = 0; i < fcn->ArgumentCount; i ++ ) - { - _put32( StringList_GetString(&strings, fcn->Arguments[i].Name, strlen(fcn->Arguments[i].Name)) ); - _put8( fcn->Arguments[i].Type ); - } - } - - // Put function code in - for(fcn = Script->Functions; fcn; fcn = fcn->Next) - { - char *code; - int len, code_pos; - - // Fix header - code_pos = ftell(fp); - fseek(fp, SEEK_SET, fcn_hdr_offset + 4); - _put32( code_pos ); - fseek(fp, SEEK_SET, code_pos ); - - fcn_hdr_offset += 4+4+1+1+(4+1)*fcn->ArgumentCount; - - // Write code - if( !fcn->BCFcn ) Bytecode_ConvertFunction(fcn); - code = Bytecode_SerialiseFunction(fcn->BCFcn, &len, &strings); - fwrite(code, len, 1, fp); - free(code); - } - - // String table - strtab_ofs = ftell(fp); - { - int string_offset = strtab_ofs + (4+4)*strings.Count; - tString *str; - // Array - for(str = strings.Head; str; str = str->Next) - { - _put32(str->Length); - _put32(string_offset); - string_offset += str->Length + 1; - } - // Data - for(str = strings.Head; str;) - { - tString *nextstr = str->Next; - fwrite(str->Data, str->Length, 1, fp); - _put8(0); - free(str); - str = nextstr; - } - strings.Head = NULL; - strings.Tail = NULL; - } - - // Fix header - fseek(fp, 8, SEEK_SET); - _put32(fcn_count); - _put32(strings.Count); - _put32(strtab_ofs); - - fclose(fp); - - return 0; -} - diff --git a/Usermode/Libraries/libspiderscript.so_src/bytecode_ops.h b/Usermode/Libraries/libspiderscript.so_src/bytecode_ops.h deleted file mode 100644 index 59c58bea..00000000 --- a/Usermode/Libraries/libspiderscript.so_src/bytecode_ops.h +++ /dev/null @@ -1,67 +0,0 @@ -/** - */ -#ifndef _BYTECODE_OPS_H_ -#define _BYTECODE_OPS_H_ - -enum eBC_Ops -{ - BC_OP_NOP, - - BC_OP_JUMP, - BC_OP_JUMPIF, - BC_OP_JUMPIFNOT, - - BC_OP_RETURN, // = 4 - BC_OP_CALLFUNCTION, - BC_OP_CALLMETHOD, - BC_OP_CREATEOBJ, - - BC_OP_LOADVAR, // = 8 - BC_OP_SAVEVAR, - - BC_OP_LOADINT, // = 10 - BC_OP_LOADREAL, - BC_OP_LOADSTR, - - BC_OP_DUPSTACK, // = 13 - BC_OP_DELSTACK, // - BC_OP_CAST, // - - BC_OP_ELEMENT, // = 16 - BC_OP_INDEX, - - BC_OP_ENTERCONTEXT, // = 18 - BC_OP_LEAVECONTEXT, - BC_OP_DEFINEVAR, - - // Operations - BC_OP_LOGICNOT, // 21 - BC_OP_LOGICAND, - BC_OP_LOGICOR, - BC_OP_LOGICXOR, - - BC_OP_BITNOT, // 25 - BC_OP_BITAND, - BC_OP_BITOR, - BC_OP_BITXOR, - - BC_OP_BITSHIFTLEFT, // 29 - BC_OP_BITSHIFTRIGHT, - BC_OP_BITROTATELEFT, - - BC_OP_NEG, // 32 - BC_OP_ADD, - BC_OP_SUBTRACT, - BC_OP_MULTIPLY, - BC_OP_DIVIDE, - BC_OP_MODULO, - - BC_OP_EQUALS, // 38 - BC_OP_NOTEQUALS, - BC_OP_LESSTHAN, - BC_OP_LESSTHANOREQUAL, - BC_OP_GREATERTHAN, - BC_OP_GREATERTHANOREQUAL -}; - -#endif diff --git a/Usermode/Libraries/libspiderscript.so_src/bytecode_optimise.c b/Usermode/Libraries/libspiderscript.so_src/bytecode_optimise.c deleted file mode 100644 index 3da6aa5a..00000000 --- a/Usermode/Libraries/libspiderscript.so_src/bytecode_optimise.c +++ /dev/null @@ -1,19 +0,0 @@ -/* - * SpiderScript Library - * by John Hodge (thePowersGang) - * - * bytecode_gen.c - * - Generate bytecode - */ -#include -#include "bytecode_ops.h" - -// Patterns: -// TODO: Figure out what optimisations can be done - -int Bytecode_OptimizeFunction(tBC_Function *Function) -{ - for( op = Function->Operations; op; op = op->Next, idx ++ ) - { - } -} diff --git a/Usermode/Libraries/libspiderscript.so_src/common.h b/Usermode/Libraries/libspiderscript.so_src/common.h deleted file mode 100644 index f2bb3e63..00000000 --- a/Usermode/Libraries/libspiderscript.so_src/common.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * SpiderScript - * - By John Hodge (thePowersGang) - */ -#ifndef _COMMON_H_ -#define _COMMON_H_ - -#include - -typedef struct sScript_Function tScript_Function; -typedef struct sScript_Arg tScript_Arg; - -struct sSpiderScript -{ - tSpiderVariant *Variant; - tScript_Function *Functions; - tScript_Function *LastFunction; - char *CurNamespace; //!< Current namespace prefix (NULL = Root) - No trailing . -}; - -struct sScript_Arg -{ - int Type; - char *Name; -}; - -struct sScript_Function -{ - tScript_Function *Next; - // char *Namespace; - char *Name; - - int ReturnType; - - struct sAST_Node *ASTFcn; - struct sBC_Function *BCFcn; - - int ArgumentCount; - tScript_Arg Arguments[]; -}; - -#endif - diff --git a/Usermode/Libraries/libspiderscript.so_src/exec.c b/Usermode/Libraries/libspiderscript.so_src/exec.c deleted file mode 100644 index b073cbf0..00000000 --- a/Usermode/Libraries/libspiderscript.so_src/exec.c +++ /dev/null @@ -1,342 +0,0 @@ -/* -* SpiderScript Library -* by John Hodge (thePowersGang) -* -* bytecode_makefile.c -* - Generate a bytecode file -*/ -#include -#include "common.h" -#include "ast.h" -#include -#include -#include - -// === IMPORTS === -extern tSpiderFunction *gpExports_First; -extern tSpiderValue *AST_ExecuteFunction(tSpiderScript *Script, tScript_Function *Fcn, int NArguments, tSpiderValue **Arguments); -extern tSpiderValue *Bytecode_ExecuteFunction(tSpiderScript *Script, tScript_Function *Fcn, int NArguments, tSpiderValue **Args); - -// === PROTOTYPES === -void AST_RuntimeMessage(tAST_Node *Node, const char *Type, const char *Format, ...); -void AST_RuntimeError(tAST_Node *Node, const char *Format, ...); - -// === CODE === -/** - * \brief Execute a script function - * \param Script Script context to execute in - * \param Namespace Namespace to search for the function - * \param Function Function name to execute - * \param NArguments Number of arguments to pass - * \param Arguments Arguments passed - */ -tSpiderValue *SpiderScript_ExecuteFunction(tSpiderScript *Script, - tSpiderNamespace *Namespace, const char *Function, - int NArguments, tSpiderValue **Arguments) -{ - int bFound = 0; // Used to keep nesting levels down - tSpiderValue *ret = ERRPTR; - - // First: Find the function in the script - { - tScript_Function *fcn; - for( fcn = Script->Functions; fcn; fcn = fcn->Next ) - { - if( strcmp(fcn->Name, Function) == 0 ) - break; - } - // Execute! - if(fcn) - { - if( fcn->BCFcn ) - ret = Bytecode_ExecuteFunction(Script, fcn, NArguments, Arguments); - else - ret = AST_ExecuteFunction(Script, fcn, NArguments, Arguments); - bFound = 1; - } - } - - // Didn't find it in script? - if(!bFound) - { - tSpiderFunction *fcn; - fcn = NULL; // Just to allow the below code to be neat - - // Second: Scan current namespace - if( !fcn && Namespace ) - { - for( fcn = Namespace->Functions; fcn; fcn = fcn->Next ) - { - if( strcmp( fcn->Name, Function ) == 0 ) - break; - } - } - - // Third: Search the variant's global exports - if( !fcn ) - { - for( fcn = Script->Variant->Functions; fcn; fcn = fcn->Next ) - { - if( strcmp( fcn->Name, Function ) == 0 ) - break; - } - } - - // Fourth: Search language exports - if( !fcn ) - { - for( fcn = gpExports_First; fcn; fcn = fcn->Next ) - { - if( strcmp( fcn->Name, Function ) == 0 ) - break; - } - } - - // Execute! - if(fcn) - { - // TODO: Type Checking - ret = fcn->Handler( Script, NArguments, Arguments ); - bFound = 1; - } - } - - // Not found? - if(!bFound) - { - fprintf(stderr, "Undefined reference to function '%s' (ns='%s')\n", - Function, Namespace->Name); - return ERRPTR; - } - - return ret; -} - -/** - * \brief Execute an object method function - * \param Script Script context to execute in - * \param Object Object in which to find the method - * \param MethodName Name of method to call - * \param NArguments Number of arguments to pass - * \param Arguments Arguments passed - */ -tSpiderValue *SpiderScript_ExecuteMethod(tSpiderScript *Script, - tSpiderObject *Object, const char *MethodName, - int NArguments, tSpiderValue **Arguments) -{ - tSpiderFunction *fcn; - tSpiderValue this; - tSpiderValue *newargs[NArguments+1]; - int i; - - // TODO: Support program defined objects - - // Search for the function - for( fcn = Object->Type->Methods; fcn; fcn = fcn->Next ) - { - if( strcmp(fcn->Name, MethodName) == 0 ) - break; - } - // Error - if( !fcn ) - { - AST_RuntimeError(NULL, "Class '%s' does not have a method '%s'", - Object->Type->Name, MethodName); - return ERRPTR; - } - - // Create the "this" argument - this.Type = SS_DATATYPE_OBJECT; - this.ReferenceCount = 1; - this.Object = Object; - newargs[0] = &this; - memcpy(&newargs[1], Arguments, NArguments*sizeof(tSpiderValue*)); - - // Check the type of the arguments - for( i = 0; fcn->ArgTypes[i]; i ++ ) - { - if( i >= NArguments ) { - for( ; fcn->ArgTypes[i]; i ++ ) ; - AST_RuntimeError(NULL, "Argument count mismatch (%i passed, %i expected)", - NArguments, i); - return ERRPTR; - } - if( Arguments[i] && Arguments[i]->Type != fcn->ArgTypes[i] ) - { - AST_RuntimeError(NULL, "Argument type mismatch (%i, expected %i)", - Arguments[i]->Type, fcn->ArgTypes[i]); - return ERRPTR; - } - } - - // Call handler - return fcn->Handler(Script, NArguments+1, newargs); -} - -/** - * \brief Execute a script function - * \param Script Script context to execute in - * \param Function Function name to execute - * \param NArguments Number of arguments to pass - * \param Arguments Arguments passed - */ -tSpiderValue *SpiderScript_CreateObject(tSpiderScript *Script, - tSpiderNamespace *Namespace, const char *ClassName, - int NArguments, tSpiderValue **Arguments) -{ - int bFound = 0; // Used to keep nesting levels down - tSpiderValue *ret = ERRPTR; - tSpiderObjectDef *class; - - // First: Find the function in the script - // TODO: Implement script-defined classes - #if 0 - { - tAST_Function *astClass; - for( astClass = Script->Script->Classes; astClass; astClass = astClass->Next ) - { - if( strcmp(astClass->Name, ClassName) == 0 ) - break; - } - // Execute! - if(astClass) - { - tAST_BlockState bs; - tAST_Node *arg; - int i = 0; - - // Build a block State - bs.FirstVar = NULL; - bs.RetVal = NULL; - bs.Parent = NULL; - bs.BaseNamespace = &Script->Variant->RootNamespace; - bs.CurNamespace = NULL; - bs.Script = Script; - bs.Ident = giNextBlockIdent ++; - - for( arg = astFcn->Arguments; arg; arg = arg->NextSibling, i++ ) - { - if( i >= NArguments ) break; // TODO: Return gracefully - // TODO: Type checks - Variable_Define(&bs, - arg->DefVar.DataType, arg->DefVar.Name, - Arguments[i]); - } - - // Execute function - ret = AST_ExecuteNode(&bs, astFcn->Code); - if( ret != ERRPTR ) - { - SpiderScript_DereferenceValue(ret); // Dereference output of last block statement - ret = bs.RetVal; // Set to return value of block - } - bFound = 1; - - while(bs.FirstVar) - { - tAST_Variable *nextVar = bs.FirstVar->Next; - Variable_Destroy( bs.FirstVar ); - bs.FirstVar = nextVar; - } - } - } - #endif - - // Didn't find it in script? - if(!bFound) - { - class = NULL; // Just to allow the below code to be neat - - //if( !Namespace ) - // Namespace = &Script->Variant->RootNamespace; - - // Second: Scan current namespace - if( !class && Namespace ) - { - for( class = Namespace->Classes; class; class = class->Next ) - { - if( strcmp( class->Name, ClassName ) == 0 ) - break; - } - } - - #if 0 - // Third: Search the variant's global exports - if( !class ) - { - for( class = Script->Variant->Classes; class; class = fcn->Next ) - { - if( strcmp( class->Name, Function ) == 0 ) - break; - } - } - #endif - - #if 0 - // Fourth: Search language exports - if( !class ) - { - for( class = gpExports_First; class; class = fcn->Next ) - { - if( strcmp( class->Name, ClassName ) == 0 ) - break; - } - } - #endif - - // Execute! - if(class) - { - tSpiderObject *obj; - // TODO: Type Checking - - // Call constructor - obj = class->Constructor( NArguments, Arguments ); - if( obj == NULL || obj == ERRPTR ) - return (void *)obj; - - // Creatue return object - ret = malloc( sizeof(tSpiderValue) ); - ret->Type = SS_DATATYPE_OBJECT; - ret->ReferenceCount = 1; - ret->Object = obj; - bFound = 1; - } - } - - // Not found? - if(!bFound) - { - fprintf(stderr, "Undefined reference to class '%s'\n", ClassName); - return ERRPTR; - } - - return ret; -} - -void AST_RuntimeMessage(tAST_Node *Node, const char *Type, const char *Format, ...) -{ - va_list args; - - if(Node) { - fprintf(stderr, "%s:%i: ", Node->File, Node->Line); - } - fprintf(stderr, "%s: ", Type); - va_start(args, Format); - vfprintf(stderr, Format, args); - va_end(args); - fprintf(stderr, "\n"); -} -void AST_RuntimeError(tAST_Node *Node, const char *Format, ...) -{ - va_list args; - - if(Node) { - fprintf(stderr, "%s:%i: ", Node->File, Node->Line); - } - fprintf(stderr, "error: "); - va_start(args, Format); - vfprintf(stderr, Format, args); - va_end(args); - fprintf(stderr, "\n"); -} diff --git a/Usermode/Libraries/libspiderscript.so_src/exec_ast.c b/Usermode/Libraries/libspiderscript.so_src/exec_ast.c deleted file mode 100644 index 7a94dc42..00000000 --- a/Usermode/Libraries/libspiderscript.so_src/exec_ast.c +++ /dev/null @@ -1,1062 +0,0 @@ -/* - * SpiderScript Library - * - * AST Execution - */ -#include -#include -#include -#include -#include "common.h" -#include "ast.h" - -#define TRACE_VAR_LOOKUPS 0 -#define TRACE_NODE_RETURNS 0 - -// === IMPORTS === - -// === PROTOTYPES === -// - Node Execution -tSpiderValue *AST_ExecuteNode(tAST_BlockState *Block, tAST_Node *Node); -tSpiderValue *AST_ExecuteNode_BinOp(tSpiderScript *Script, tAST_Node *Node, int Operation, tSpiderValue *Left, tSpiderValue *Right); -tSpiderValue *AST_ExecuteNode_UniOp(tSpiderScript *Script, tAST_Node *Node, int Operation, tSpiderValue *Value); -// - Variables -tAST_Variable *Variable_Define(tAST_BlockState *Block, int Type, const char *Name, tSpiderValue *Value); - int Variable_SetValue(tAST_BlockState *Block, tAST_Node *VarNode, tSpiderValue *Value); -tSpiderValue *Variable_GetValue(tAST_BlockState *Block, tAST_Node *VarNode); -void Variable_Destroy(tAST_Variable *Variable); -// - Errors -void AST_RuntimeMessage(tAST_Node *Node, const char *Type, const char *Format, ...); -void AST_RuntimeError(tAST_Node *Node, const char *Format, ...); - -// === GLOBALS === - int giNextBlockIdent = 1; - -// === CODE === -tSpiderValue *AST_ExecuteFunction(tSpiderScript *Script, tScript_Function *Fcn, int NArguments, tSpiderValue **Arguments) -{ - tAST_BlockState bs; - tSpiderValue *ret; - int i = 0; - - // Build a block State - bs.FirstVar = NULL; - bs.RetVal = NULL; - bs.Parent = NULL; - bs.BaseNamespace = &Script->Variant->RootNamespace; - bs.CurNamespace = NULL; - bs.Script = Script; - bs.Ident = giNextBlockIdent ++; - - // Parse arguments - for( i = 0; i < Fcn->ArgumentCount; i ++ ) - { - if( i >= NArguments ) break; // TODO: Return gracefully - // TODO: Type checks - Variable_Define(&bs, - Fcn->Arguments[i].Type, Fcn->Arguments[i].Name, - Arguments[i]); - } - - // Execute function - ret = AST_ExecuteNode(&bs, Fcn->ASTFcn); - if(ret != ERRPTR) - { - SpiderScript_DereferenceValue(ret); // Dereference output of last block statement - ret = bs.RetVal; // Set to return value of block - } - - while(bs.FirstVar) - { - tAST_Variable *nextVar = bs.FirstVar->Next; - Variable_Destroy( bs.FirstVar ); - bs.FirstVar = nextVar; - } - return ret; -} - -/** - * \brief Execute an AST node and return its value - * \param Block Execution context - * \param Node Node to execute - */ -tSpiderValue *AST_ExecuteNode(tAST_BlockState *Block, tAST_Node *Node) -{ - tAST_Node *node; - tSpiderValue *ret = NULL, *tmpobj; - tSpiderValue *op1, *op2; // Binary operations - int i; - - switch(Node->Type) - { - // No Operation - case NODETYPE_NOP: - ret = NULL; - break; - - // Code block - case NODETYPE_BLOCK: - { - tAST_BlockState blockInfo; - blockInfo.Parent = Block; - blockInfo.Script = Block->Script; - blockInfo.FirstVar = NULL; - blockInfo.RetVal = NULL; - blockInfo.BaseNamespace = Block->BaseNamespace; - blockInfo.CurNamespace = NULL; - blockInfo.BreakTarget = NULL; - blockInfo.Ident = giNextBlockIdent ++; - ret = NULL; - // Loop over all nodes, or until the return value is set - for(node = Node->Block.FirstChild; - node && !blockInfo.RetVal && !blockInfo.BreakTarget; - node = node->NextSibling ) - { - ret = AST_ExecuteNode(&blockInfo, node); - if(ret == ERRPTR) break; // Error check - if(ret != NULL) SpiderScript_DereferenceValue(ret); // Free unused value - } - // Clean up variables - while(blockInfo.FirstVar) - { - tAST_Variable *nextVar = blockInfo.FirstVar->Next; - Variable_Destroy( blockInfo.FirstVar ); - blockInfo.FirstVar = nextVar; - } - // Clear ret if not an error - if(ret != ERRPTR) ret = NULL; - - // Set parent's return value if needed - if( blockInfo.RetVal ) - Block->RetVal = blockInfo.RetVal; - if( blockInfo.BreakTarget ) { - Block->BreakTarget = blockInfo.BreakTarget; - Block->BreakType = blockInfo.BreakType; - } - - // TODO: Unset break if break type deontes a block break - } - - break; - - // Assignment - case NODETYPE_ASSIGN: - // TODO: Support assigning to object attributes - if( Node->Assign.Dest->Type != NODETYPE_VARIABLE ) { - AST_RuntimeError(Node, "LVALUE of assignment is not a variable"); - return ERRPTR; - } - ret = AST_ExecuteNode(Block, Node->Assign.Value); - if(ret == ERRPTR) return ERRPTR; - - // Perform assignment operation - if( Node->Assign.Operation != NODETYPE_NOP ) - { - tSpiderValue *varVal, *value; - - varVal = Variable_GetValue(Block, Node->Assign.Dest); - if(varVal == ERRPTR) return ERRPTR; - #if 0 - #else - if(varVal && varVal->ReferenceCount == 2) { - SpiderScript_DereferenceValue(varVal); -// printf("pre: (%s) varVal->ReferenceCount = %i\n", -// Node->Assign.Dest->Variable.Name, -// varVal->ReferenceCount); - } - #endif - value = AST_ExecuteNode_BinOp(Block->Script, Node, Node->Assign.Operation, varVal, ret); - if(value == ERRPTR) return ERRPTR; - - if(ret) SpiderScript_DereferenceValue(ret); - #if 0 - if(varVal) SpiderScript_DereferenceValue(varVal); - #else - if(varVal && varVal->ReferenceCount == 1) { - SpiderScript_ReferenceValue(varVal); -// printf("post: varVal->ReferenceCount = %i\n", varVal->ReferenceCount); - break; // If varVal was non-null, it has been updated by _BinOp - } - #endif - // Else, it was NULL, so has to be assigned - ret = value; - } - - // Set the variable value - if( Variable_SetValue( Block, Node->Assign.Dest, ret ) ) { - SpiderScript_DereferenceValue( ret ); - return ERRPTR; - } - break; - - // Post increment/decrement - case NODETYPE_POSTINC: - case NODETYPE_POSTDEC: - { - tSpiderValue *varVal, *value; - static tSpiderValue one = { - .Type = SS_DATATYPE_INTEGER, - .ReferenceCount = 1, - {.Integer = 1} - }; - - // TODO: Support assigning to object attributes - if( Node->UniOp.Value->Type != NODETYPE_VARIABLE ) { - AST_RuntimeError(Node, "LVALUE of assignment is not a variable"); - return ERRPTR; - } - - // Get values (current variable contents and a static one) - varVal = Variable_GetValue(Block, Node->UniOp.Value); - - if( Node->Type == NODETYPE_POSTDEC ) - value = AST_ExecuteNode_BinOp(Block->Script, Node, NODETYPE_SUBTRACT, varVal, &one); - else - value = AST_ExecuteNode_BinOp(Block->Script, Node, NODETYPE_ADD, varVal, &one); - if( value == ERRPTR ) - return ERRPTR; - - ret = varVal; - - if( Variable_SetValue( Block, Node->UniOp.Value, value ) ) { - SpiderScript_DereferenceValue( ret ); - return ERRPTR; - } - SpiderScript_DereferenceValue( value ); - } - break; - - // Function Call - case NODETYPE_METHODCALL: - case NODETYPE_FUNCTIONCALL: - case NODETYPE_CREATEOBJECT: - // Logical block (used to allocate `params`) - { - tSpiderNamespace *ns = Block->CurNamespace; - tSpiderValue *params[Node->FunctionCall.NumArgs]; - i = 0; - for(node = Node->FunctionCall.FirstArg; node; node = node->NextSibling) - { - params[i] = AST_ExecuteNode(Block, node); - if( params[i] == ERRPTR ) { - while(i--) SpiderScript_DereferenceValue(params[i]); - ret = ERRPTR; - goto _return; - } - i ++; - } - - if( !ns ) ns = Block->BaseNamespace; - - // Call the function - if( Node->Type == NODETYPE_CREATEOBJECT ) - { - ret = SpiderScript_CreateObject(Block->Script, - ns, - Node->FunctionCall.Name, - Node->FunctionCall.NumArgs, params - ); - } - else if( Node->Type == NODETYPE_METHODCALL ) - { - tSpiderValue *obj = AST_ExecuteNode(Block, Node->FunctionCall.Object); - if( !obj || obj == ERRPTR || obj->Type != SS_DATATYPE_OBJECT ) { - AST_RuntimeError(Node->FunctionCall.Object, - "Type Mismatch - Required SS_DATATYPE_OBJECT for method call"); - while(i--) SpiderScript_DereferenceValue(params[i]); - ret = ERRPTR; - break; - } - ret = SpiderScript_ExecuteMethod(Block->Script, - obj->Object, Node->FunctionCall.Name, - Node->FunctionCall.NumArgs, params - ); - SpiderScript_DereferenceValue(obj); - } - else - { - ret = SpiderScript_ExecuteFunction(Block->Script, - ns, Node->FunctionCall.Name, - Node->FunctionCall.NumArgs, params - ); - } - - - // Dereference parameters - while(i--) SpiderScript_DereferenceValue(params[i]); - - // falls out - } - break; - - // Conditional - case NODETYPE_IF: - ret = AST_ExecuteNode(Block, Node->If.Condition); - if( ret == ERRPTR ) break; - if( SpiderScript_IsValueTrue(ret) ) { - tmpobj = AST_ExecuteNode(Block, Node->If.True); - } - else { - tmpobj = AST_ExecuteNode(Block, Node->If.False); - } - SpiderScript_DereferenceValue(ret); - if( tmpobj == ERRPTR ) return ERRPTR; - SpiderScript_DereferenceValue(tmpobj); - ret = NULL; - break; - - // Loop - case NODETYPE_LOOP: - // Initialise - ret = AST_ExecuteNode(Block, Node->For.Init); - if(ret == ERRPTR) break; - - // Check initial condition - if( !Node->For.bCheckAfter ) - { - SpiderScript_DereferenceValue(ret); - - ret = AST_ExecuteNode(Block, Node->For.Condition); - if(ret == ERRPTR) return ERRPTR; - if(!SpiderScript_IsValueTrue(ret)) { - SpiderScript_DereferenceValue(ret); - ret = NULL; - break; - } - } - - // Perform loop - for( ;; ) - { - SpiderScript_DereferenceValue(ret); - - // Code - ret = AST_ExecuteNode(Block, Node->For.Code); - if(ret == ERRPTR) return ERRPTR; - SpiderScript_DereferenceValue(ret); - - if(Block->BreakTarget) - { - if( Block->BreakTarget[0] == '\0' || strcmp(Block->BreakTarget, Node->For.Tag) == 0 ) - { - // Ours - free((void*)Block->BreakTarget); Block->BreakTarget = NULL; - if( Block->BreakType == NODETYPE_CONTINUE ) { - // Continue, just keep going - } - else - break; - } - else - break; // Break out of this loop - } - - // Increment - ret = AST_ExecuteNode(Block, Node->For.Increment); - if(ret == ERRPTR) return ERRPTR; - SpiderScript_DereferenceValue(ret); - - // Check condition - ret = AST_ExecuteNode(Block, Node->For.Condition); - if(ret == ERRPTR) return ERRPTR; - if(!SpiderScript_IsValueTrue(ret)) break; - } - SpiderScript_DereferenceValue(ret); - ret = NULL; - break; - - // Return - case NODETYPE_RETURN: - ret = AST_ExecuteNode(Block, Node->UniOp.Value); - if(ret == ERRPTR) break; - Block->RetVal = ret; // Return value set - ret = NULL; // the `return` statement does not return a value - break; - - case NODETYPE_BREAK: - case NODETYPE_CONTINUE: - Block->BreakTarget = strdup(Node->Variable.Name); - Block->BreakType = Node->Type; - break; - - // Define a variable - case NODETYPE_DEFVAR: - if( Node->DefVar.InitialValue ) { - tmpobj = AST_ExecuteNode(Block, Node->DefVar.InitialValue); - if(tmpobj == ERRPTR) return ERRPTR; - } - else { - tmpobj = NULL; - } - // TODO: Handle arrays - ret = NULL; - if( Variable_Define(Block, Node->DefVar.DataType, Node->DefVar.Name, tmpobj) == ERRPTR ) - ret = ERRPTR; - SpiderScript_DereferenceValue(tmpobj); - break; - - // Scope - case NODETYPE_SCOPE: - { - tSpiderNamespace *ns; - - // Set current namespace if unset - if( !Block->CurNamespace ) - Block->CurNamespace = Block->BaseNamespace; - - // Empty string means use the root namespace - if( Node->Scope.Name[0] == '\0' ) - { - ns = &Block->Script->Variant->RootNamespace; - } - else - { - // Otherwise scan the current namespace for the element - for( ns = Block->CurNamespace->FirstChild; ns; ns = ns->Next ) - { - if( strcmp(ns->Name, Node->Scope.Name) == 0 ) - break; - } - } - if(!ns) { - AST_RuntimeError(Node, "Unknown namespace '%s'", Node->Scope.Name); - ret = ERRPTR; - break; - } - Block->CurNamespace = ns; - - ret = AST_ExecuteNode(Block, Node->Scope.Element); - } - break; - - // Variable - case NODETYPE_VARIABLE: - ret = Variable_GetValue( Block, Node ); - break; - - // Element of an Object - case NODETYPE_ELEMENT: - tmpobj = AST_ExecuteNode( Block, Node->Scope.Element ); - if(tmpobj == ERRPTR) return ERRPTR; - if( !tmpobj || tmpobj->Type != SS_DATATYPE_OBJECT ) - { - AST_RuntimeError(Node->Scope.Element, "Unable to dereference a non-object"); - ret = ERRPTR; - break ; - } - - for( i = 0; i < tmpobj->Object->Type->NAttributes; i ++ ) - { - if( strcmp(Node->Scope.Name, tmpobj->Object->Type->AttributeDefs[i].Name) == 0 ) - { - ret = tmpobj->Object->Attributes[i]; - SpiderScript_ReferenceValue(ret); - break; - } - } - if( i == tmpobj->Object->Type->NAttributes ) - { - AST_RuntimeError(Node->Scope.Element, "Unknown attribute '%s' of class '%s'", - Node->Scope.Name, tmpobj->Object->Type->Name); - ret = ERRPTR; - } - break; - - // Cast a value to another - case NODETYPE_CAST: - { - tmpobj = AST_ExecuteNode(Block, Node->Cast.Value); - if(tmpobj == ERRPTR) return ERRPTR; - ret = SpiderScript_CastValueTo( Node->Cast.DataType, tmpobj ); - SpiderScript_DereferenceValue(tmpobj); - } - break; - - // Index into an array - case NODETYPE_INDEX: - op1 = AST_ExecuteNode(Block, Node->BinOp.Left); // Array - if(op1 == ERRPTR) return ERRPTR; - op2 = AST_ExecuteNode(Block, Node->BinOp.Right); // Offset - if(op2 == ERRPTR) { - SpiderScript_DereferenceValue(op1); - return ERRPTR; - } - - if( !op1 || op1->Type != SS_DATATYPE_ARRAY ) - { - // TODO: Implement "operator []" on objects - AST_RuntimeError(Node, "Indexing non-array"); - ret = ERRPTR; - break; - } - - if( (!op2 || op2->Type != SS_DATATYPE_INTEGER) && !Block->Script->Variant->bImplicitCasts ) { - AST_RuntimeError(Node, "Array index is not an integer"); - ret = ERRPTR; - break; - } - - if( !op2 || op2->Type != SS_DATATYPE_INTEGER ) - { - tmpobj = SpiderScript_CastValueTo(SS_DATATYPE_INTEGER, op2); - SpiderScript_DereferenceValue(op2); - op2 = tmpobj; - } - - if( op2->Integer >= op1->Array.Length ) { - AST_RuntimeError(Node, "Array index out of bounds %i >= %i", - op2->Integer, op1->Array.Length); - ret = ERRPTR; - break; - } - - ret = op1->Array.Items[ op2->Integer ]; - SpiderScript_ReferenceValue(ret); - - SpiderScript_DereferenceValue(op1); - SpiderScript_DereferenceValue(op2); - break; - - // TODO: Implement runtime constants - case NODETYPE_CONSTANT: - // TODO: Scan namespace for constant name - AST_RuntimeError(Node, "TODO - Runtime Constants"); - ret = ERRPTR; - break; - - // Constant Values - case NODETYPE_STRING: - case NODETYPE_INTEGER: - case NODETYPE_REAL: - ret = &Node->Constant; - SpiderScript_ReferenceValue(ret); - break; - - // --- Operations --- - // Boolean Operations - case NODETYPE_LOGICALNOT: // Logical NOT (!) - op1 = AST_ExecuteNode(Block, Node->UniOp.Value); - if(op1 == ERRPTR) return ERRPTR; - ret = SpiderScript_CreateInteger( !SpiderScript_IsValueTrue(op1) ); - SpiderScript_DereferenceValue(op1); - break; - case NODETYPE_LOGICALAND: // Logical AND (&&) - case NODETYPE_LOGICALOR: // Logical OR (||) - case NODETYPE_LOGICALXOR: // Logical XOR (^^) - op1 = AST_ExecuteNode(Block, Node->BinOp.Left); - if(op1 == ERRPTR) return ERRPTR; - op2 = AST_ExecuteNode(Block, Node->BinOp.Right); - if(op2 == ERRPTR) { - SpiderScript_DereferenceValue(op1); - return ERRPTR; - } - - switch( Node->Type ) - { - case NODETYPE_LOGICALAND: - ret = SpiderScript_CreateInteger( SpiderScript_IsValueTrue(op1) && SpiderScript_IsValueTrue(op2) ); - break; - case NODETYPE_LOGICALOR: - ret = SpiderScript_CreateInteger( SpiderScript_IsValueTrue(op1) || SpiderScript_IsValueTrue(op2) ); - break; - case NODETYPE_LOGICALXOR: - ret = SpiderScript_CreateInteger( SpiderScript_IsValueTrue(op1) ^ SpiderScript_IsValueTrue(op2) ); - break; - default: break; - } - - // Free intermediate objects - SpiderScript_DereferenceValue(op1); - SpiderScript_DereferenceValue(op2); - break; - - // General Unary Operations - case NODETYPE_BWNOT: // Bitwise NOT (~) - case NODETYPE_NEGATE: // Negation (-) - op1 = AST_ExecuteNode(Block, Node->UniOp.Value); - if(op1 == ERRPTR) return ERRPTR; - ret = AST_ExecuteNode_UniOp(Block->Script, Node, Node->Type, op1); - SpiderScript_DereferenceValue(op1); - break; - - // General Binary Operations - case NODETYPE_ADD: - case NODETYPE_SUBTRACT: - case NODETYPE_MULTIPLY: - case NODETYPE_DIVIDE: - case NODETYPE_MODULO: - case NODETYPE_BWAND: - case NODETYPE_BWOR: - case NODETYPE_BWXOR: - case NODETYPE_BITSHIFTLEFT: - case NODETYPE_BITSHIFTRIGHT: - case NODETYPE_BITROTATELEFT: - case NODETYPE_EQUALS: - case NODETYPE_LESSTHAN: - case NODETYPE_GREATERTHAN: - case NODETYPE_LESSTHANEQUAL: - case NODETYPE_GREATERTHANEQUAL: - // Get operands - op1 = AST_ExecuteNode(Block, Node->BinOp.Left); - if(op1 == ERRPTR) return ERRPTR; - op2 = AST_ExecuteNode(Block, Node->BinOp.Right); - if(op2 == ERRPTR) { - SpiderScript_DereferenceValue(op1); - return ERRPTR; - } - - ret = AST_ExecuteNode_BinOp(Block->Script, Node, Node->Type, op1, op2); - - // Free intermediate objects - SpiderScript_DereferenceValue(op1); - SpiderScript_DereferenceValue(op2); - break; - - //default: - // ret = NULL; - // AST_RuntimeError(Node, "BUG - SpiderScript AST_ExecuteNode Unimplemented %i", Node->Type); - // break; - } -_return: - // Reset namespace when no longer needed - if( Node->Type != NODETYPE_SCOPE ) - Block->CurNamespace = NULL; - - #if TRACE_NODE_RETURNS - if(ret && ret != ERRPTR) { - AST_RuntimeError(Node, "Ret type of %p %i is %i", Node, Node->Type, ret->Type); - } - else { - AST_RuntimeError(Node, "Ret type of %p %i is %p", Node, Node->Type, ret); - } - #endif - - return ret; -} - -tSpiderValue *AST_ExecuteNode_UniOp(tSpiderScript *Script, tAST_Node *Node, int Operation, tSpiderValue *Value) -{ - tSpiderValue *ret; - #if 0 - if( Value->Type == SS_DATATYPE_OBJECT ) - { - const char *fcnname; - switch(Operation) - { - case NODETYPE_NEGATE: fcnname = "-ve"; break; - case NODETYPE_BWNOT: fcnname = "~"; break; - default: fcnname = NULL; break; - } - - if( fcnname ) - { - ret = Object_ExecuteMethod(Value->Object, fcnname, ); - if( ret != ERRPTR ) - return ret; - } - } - #endif - switch(Value->Type) - { - // Integer Operations - case SS_DATATYPE_INTEGER: - if( Value->ReferenceCount == 1 ) - SpiderScript_ReferenceValue(ret = Value); - else - ret = SpiderScript_CreateInteger(0); - switch(Operation) - { - case NODETYPE_NEGATE: ret->Integer = -Value->Integer; break; - case NODETYPE_BWNOT: ret->Integer = ~Value->Integer; break; - default: - AST_RuntimeError(Node, "SpiderScript internal error: Exec,UniOP,Integer unknown op %i", Operation); - SpiderScript_DereferenceValue(ret); - ret = ERRPTR; - break; - } - break; - // Real number Operations - case SS_DATATYPE_REAL: - switch(Operation) - { - case NODETYPE_NEGATE: ret = SpiderScript_CreateInteger( -Value->Real ); break; - default: - AST_RuntimeError(Node, "SpiderScript internal error: Exec,UniOP,Real unknown op %i", Operation); - ret = ERRPTR; - break; - } - break; - - default: - AST_RuntimeError(NULL, "Invalid operation (%i) on type (%i)", Operation, Value->Type); - ret = ERRPTR; - break; - } - - return ret; -} - -tSpiderValue *AST_ExecuteNode_BinOp(tSpiderScript *Script, tAST_Node *Node, int Operation, tSpiderValue *Left, tSpiderValue *Right) -{ - tSpiderValue *preCastValue = Right; - tSpiderValue *ret; - - // Convert types - if( Left && Right && Left->Type != Right->Type ) - { - #if 0 - // Object types - // - Operator overload functions - if( Left->Type == SS_DATATYPE_OBJECT ) - { - const char *fcnname; - switch(Operation) - { - case NODETYPE_ADD: fcnname = "+"; break; - case NODETYPE_SUBTRACT: fcnname = "-"; break; - case NODETYPE_MULTIPLY: fcnname = "*"; break; - case NODETYPE_DIVIDE: fcnname = "/"; break; - case NODETYPE_MODULO: fcnname = "%"; break; - case NODETYPE_BWAND: fcnname = "&"; break; - case NODETYPE_BWOR: fcnname = "|"; break; - case NODETYPE_BWXOR: fcnname = "^"; break; - case NODETYPE_BITSHIFTLEFT: fcnname = "<<"; break; - case NODETYPE_BITSHIFTRIGHT:fcnname = ">>"; break; - case NODETYPE_BITROTATELEFT:fcnname = "<<<"; break; - default: fcnname = NULL; break; - } - - if( fcnname ) - { - ret = Object_ExecuteMethod(Left->Object, fcnname, Right); - if( ret != ERRPTR ) - return ret; - // Fall through and try casting (which will usually fail) - } - } - #endif - - // If implicit casts are allowed, convert Right to Left's type - if(Script->Variant->bImplicitCasts) - { - Right = SpiderScript_CastValueTo(Left->Type, Right); - if(Right == ERRPTR) - return ERRPTR; - } - // If statically typed, this should never happen, but catch it anyway - else { - AST_RuntimeError(Node, "Implicit cast not allowed (from %i to %i)", Right->Type, Left->Type); - return ERRPTR; - } - } - - // NULL Check - if( Left == NULL || Right == NULL ) { - if(Right && Right != preCastValue) free(Right); - return NULL; - } - - // Catch comparisons - switch(Operation) - { - case NODETYPE_EQUALS: - case NODETYPE_LESSTHAN: - case NODETYPE_GREATERTHAN: - case NODETYPE_LESSTHANEQUAL: - case NODETYPE_GREATERTHANEQUAL: { - int cmp; - ret = NULL; - // Do operation - switch(Left->Type) - { - // - String Compare (does a strcmp, well memcmp) - case SS_DATATYPE_STRING: - // Call memcmp to do most of the work - cmp = memcmp( - Left->String.Data, Right->String.Data, - (Left->String.Length < Right->String.Length) ? Left->String.Length : Right->String.Length - ); - // Handle reaching the end of the string - if( cmp == 0 ) { - if( Left->String.Length == Right->String.Length ) - cmp = 0; - else if( Left->String.Length < Right->String.Length ) - cmp = 1; - else - cmp = -1; - } - break; - - // - Integer Comparisons - case SS_DATATYPE_INTEGER: - if( Left->Integer == Right->Integer ) - cmp = 0; - else if( Left->Integer < Right->Integer ) - cmp = -1; - else - cmp = 1; - break; - // - Real Number Comparisons - case SS_DATATYPE_REAL: - cmp = (Left->Real - Right->Real) / Right->Real * 10000; // < 0.1% difference is equality - break; - default: - AST_RuntimeError(Node, "TODO - Comparison of type %i", Left->Type); - ret = ERRPTR; - break; - } - - // Error check - if( ret != ERRPTR ) - { - if(Left->ReferenceCount == 1 && Left->Type != SS_DATATYPE_STRING) - SpiderScript_ReferenceValue(ret = Left); - else - ret = SpiderScript_CreateInteger(0); - - // Create return - switch(Operation) - { - case NODETYPE_EQUALS: ret->Integer = (cmp == 0); break; - case NODETYPE_LESSTHAN: ret->Integer = (cmp < 0); break; - case NODETYPE_GREATERTHAN: ret->Integer = (cmp > 0); break; - case NODETYPE_LESSTHANEQUAL: ret->Integer = (cmp <= 0); break; - case NODETYPE_GREATERTHANEQUAL: ret->Integer = (cmp >= 0); break; - default: - AST_RuntimeError(Node, "Exec,CmpOp unknown op %i", Operation); - SpiderScript_DereferenceValue(ret); - ret = ERRPTR; - break; - } - } - if(Right && Right != preCastValue) free(Right); - return ret; - } - - // Fall through and sort by type instead - default: - break; - } - - // Do operation - switch(Left->Type) - { - // String Concatenation - case SS_DATATYPE_STRING: - switch(Operation) - { - case NODETYPE_ADD: // Concatenate - ret = SpiderScript_StringConcat(Left, Right); - break; - // TODO: Support python style 'i = %i' % i ? - // Might do it via a function call - // Implement it via % with an array, but getting past the cast will be fun -// case NODETYPE_MODULUS: -// break; - // TODO: Support string repititions -// case NODETYPE_MULTIPLY: -// break; - - default: - AST_RuntimeError(Node, "SpiderScript internal error: Exec,BinOP,String unknown op %i", Operation); - ret = ERRPTR; - break; - } - break; - // Integer Operations - case SS_DATATYPE_INTEGER: - if( Left->ReferenceCount == 1 ) - SpiderScript_ReferenceValue(ret = Left); - else - ret = SpiderScript_CreateInteger(0); - switch(Operation) - { - case NODETYPE_ADD: ret->Integer = Left->Integer + Right->Integer; break; - case NODETYPE_SUBTRACT: ret->Integer = Left->Integer - Right->Integer; break; - case NODETYPE_MULTIPLY: ret->Integer = Left->Integer * Right->Integer; break; - case NODETYPE_DIVIDE: ret->Integer = Left->Integer / Right->Integer; break; - case NODETYPE_MODULO: ret->Integer = Left->Integer % Right->Integer; break; - case NODETYPE_BWAND: ret->Integer = Left->Integer & Right->Integer; break; - case NODETYPE_BWOR: ret->Integer = Left->Integer | Right->Integer; break; - case NODETYPE_BWXOR: ret->Integer = Left->Integer ^ Right->Integer; break; - case NODETYPE_BITSHIFTLEFT: ret->Integer = Left->Integer << Right->Integer; break; - case NODETYPE_BITSHIFTRIGHT:ret->Integer = Left->Integer >> Right->Integer; break; - case NODETYPE_BITROTATELEFT: - ret->Integer = (Left->Integer << Right->Integer) | (Left->Integer >> (64-Right->Integer)); - break; - default: - AST_RuntimeError(Node, "SpiderScript internal error: Exec,BinOP,Integer unknown op %i", Operation); - SpiderScript_DereferenceValue(ret); - ret = ERRPTR; - break; - } - break; - - // Real Numbers - case SS_DATATYPE_REAL: - if( Left->ReferenceCount == 1 ) - SpiderScript_ReferenceValue(ret = Left); - else - ret = SpiderScript_CreateReal(0); - switch(Operation) - { - case NODETYPE_ADD: ret->Real = Left->Real + Right->Real; break; - case NODETYPE_SUBTRACT: ret->Real = Left->Real - Right->Real; break; - case NODETYPE_MULTIPLY: ret->Real = Left->Real * Right->Real; break; - case NODETYPE_DIVIDE: ret->Real = Left->Real / Right->Real; break; - default: - AST_RuntimeError(Node, "SpiderScript internal error: Exec,BinOP,Real unknown op %i", Operation); - SpiderScript_DereferenceValue(ret); - ret = ERRPTR; - break; - } - break; - - default: - AST_RuntimeError(Node, "BUG - Invalid operation (%i) on type (%i)", Operation, Left->Type); - ret = ERRPTR; - break; - } - - if(Right && Right != preCastValue) free(Right); - - return ret; -} - -/** - * \brief Define a variable - * \param Block Current block state - * \param Type Type of the variable - * \param Name Name of the variable - * \return Boolean Failure - */ -tAST_Variable *Variable_Define(tAST_BlockState *Block, int Type, const char *Name, tSpiderValue *Value) -{ - tAST_Variable *var, *prev = NULL; - - for( var = Block->FirstVar; var; prev = var, var = var->Next ) - { - if( strcmp(var->Name, Name) == 0 ) { - AST_RuntimeError(NULL, "Redefinition of variable '%s'", Name); - return ERRPTR; - } - } - - var = malloc( sizeof(tAST_Variable) + strlen(Name) + 1 ); - var->Next = NULL; - var->Type = Type; - var->Object = Value; - if(Value) SpiderScript_ReferenceValue(Value); - strcpy(var->Name, Name); - - if(prev) prev->Next = var; - else Block->FirstVar = var; - - //printf("Defined variable %s (%i)\n", Name, Type); - - return var; -} - -tAST_Variable *Variable_Lookup(tAST_BlockState *Block, tAST_Node *VarNode, int CreateType) -{ - tAST_Variable *var = NULL; - - // Speed hack - if( VarNode->BlockState == Block && VarNode->BlockIdent == Block->Ident ) { - var = VarNode->ValueCache; - #if TRACE_VAR_LOOKUPS - AST_RuntimeMessage(VarNode, "debug", "Fast var fetch on '%s' %p (%p:%i)", - VarNode->Variable.Name, var, - VarNode->BlockState, VarNode->BlockIdent - ); - #endif - } - else - { - tAST_BlockState *bs; - for( bs = Block; bs; bs = bs->Parent ) - { - for( var = bs->FirstVar; var; var = var->Next ) - { - if( strcmp(var->Name, VarNode->Variable.Name) == 0 ) - break; - } - if(var) break; - } - - if( !var ) - { - if( Block->Script->Variant->bDyamicTyped && CreateType != SS_DATATYPE_UNDEF ) { - // Define variable - var = Variable_Define(Block, CreateType, VarNode->Variable.Name, NULL); - } - else - { - AST_RuntimeError(VarNode, "Variable '%s' is undefined", VarNode->Variable.Name); - return NULL; - } - } - - #if TRACE_VAR_LOOKUPS - AST_RuntimeMessage(VarNode, "debug", "Saved variable lookup of '%s' %p (%p:%i)", - VarNode->Variable.Name, var, - Block, Block->Ident); - #endif - - VarNode->ValueCache = var; - VarNode->BlockState = Block; - VarNode->BlockIdent = Block->Ident; - } - - return var; -} - -/** - * \brief Set the value of a variable - * \return Boolean Failure - */ -int Variable_SetValue(tAST_BlockState *Block, tAST_Node *VarNode, tSpiderValue *Value) -{ - tAST_Variable *var; - - var = Variable_Lookup(Block, VarNode, (Value ? Value->Type : SS_DATATYPE_UNDEF)); - - if( !var ) return -1; - - if( !Block->Script->Variant->bDyamicTyped && (Value && var->Type != Value->Type) ) - { - AST_RuntimeError(VarNode, "Type mismatch assigning to '%s'", - VarNode->Variable.Name); - return -2; - } - -// printf("Assign %p to '%s'\n", Value, var->Name); - SpiderScript_ReferenceValue(Value); - SpiderScript_DereferenceValue(var->Object); - var->Object = Value; - return 0; -} - -/** - * \brief Get the value of a variable - */ -tSpiderValue *Variable_GetValue(tAST_BlockState *Block, tAST_Node *VarNode) -{ - tAST_Variable *var = Variable_Lookup(Block, VarNode, 0); - - if( !var ) return ERRPTR; - - SpiderScript_ReferenceValue(var->Object); - return var->Object; -} - -/** - * \brief Destorys a variable - */ -void Variable_Destroy(tAST_Variable *Variable) -{ -// printf("Variable_Destroy: (%p'%s')\n", Variable, Variable->Name); - SpiderScript_DereferenceValue(Variable->Object); - free(Variable); -} - diff --git a/Usermode/Libraries/libspiderscript.so_src/exec_bytecode.c b/Usermode/Libraries/libspiderscript.so_src/exec_bytecode.c deleted file mode 100644 index 4673bd28..00000000 --- a/Usermode/Libraries/libspiderscript.so_src/exec_bytecode.c +++ /dev/null @@ -1,806 +0,0 @@ -/* - * SpiderScript Library - * by John Hodge (thePowersGang) - * - * exec_bytecode.c - * - Execute bytecode - */ -#include -#include -#include "common.h" -#include "bytecode.h" -#include -#include -#include "ast.h" -#include - -#define TRACE 0 - -#if TRACE -# define DEBUG_F(v...) printf(v) -#else -# define DEBUG_F(v...) -#endif - -// === IMPORTS === -extern void AST_RuntimeError(tAST_Node *Node, const char *Format, ...); - -// === TYPES === -typedef struct sBC_StackEnt tBC_StackEnt; -typedef struct sBC_Stack tBC_Stack; - -enum eBC_StackEntTypes -{ - ET_NULL, // Start of the stack - // SS_DATATYPE_* - ET_FUNCTION_START = NUM_SS_DATATYPES, - ET_REFERENCE // Reference to a tSpiderValue -}; - -struct sBC_StackEnt -{ - uint8_t Type; - union { - int64_t Integer; - double Real; - tSpiderValue *Reference; // Used for everything else - tSpiderObject *Object; - tSpiderNamespace *Namespace; - }; -}; - -struct sBC_Stack -{ - int EntrySpace; - int EntryCount; - tBC_StackEnt Entries[]; -}; - -// === PROTOTYPES === -tSpiderValue *Bytecode_ExecuteFunction(tSpiderScript *Script, tScript_Function *Fcn, int NArguments, tSpiderValue **Args); - int Bytecode_int_ExecuteFunction(tSpiderScript *Script, tScript_Function *Fcn, tBC_Stack *Stack, int ArgCount); - -// === CODE === -int Bytecode_int_StackPop(tBC_Stack *Stack, tBC_StackEnt *Dest) -{ - if( Stack->EntryCount == 0 ) return 1; - Stack->EntryCount --; - *Dest = Stack->Entries[Stack->EntryCount]; - return 0; -} - -int Bytecode_int_StackPush(tBC_Stack *Stack, tBC_StackEnt *Src) -{ - if( Stack->EntryCount == Stack->EntrySpace ) return 1; - Stack->Entries[Stack->EntryCount] = *Src; - Stack->EntryCount ++; - return 0; -} - -int Bytecode_int_IsStackEntTrue(tBC_StackEnt *Ent) -{ - switch(Ent->Type) - { - case SS_DATATYPE_INTEGER: - return !!Ent->Integer; - case SS_DATATYPE_REAL: - return (-.5f < Ent->Real && Ent->Real < 0.5f); - case SS_DATATYPE_OBJECT: - return Ent->Object != NULL; - case ET_FUNCTION_START: - return -1; - default: - return SpiderScript_IsValueTrue(Ent->Reference); - } -} - -tSpiderValue *Bytecode_int_GetSpiderValue(tBC_StackEnt *Ent, tSpiderValue *tmp) -{ - switch(Ent->Type) - { - case SS_DATATYPE_INTEGER: - case SS_DATATYPE_REAL: - case SS_DATATYPE_OBJECT: - if(!tmp) { - tmp = malloc(sizeof(tSpiderValue)); - tmp->ReferenceCount = 1; - } else { - tmp->ReferenceCount = 2; - } - break; - default: - break; - } - switch(Ent->Type) - { - case SS_DATATYPE_INTEGER: - tmp->Type = SS_DATATYPE_INTEGER; - tmp->Integer = Ent->Integer; - return tmp; - case SS_DATATYPE_REAL: - tmp->Type = SS_DATATYPE_REAL; - tmp->Real = Ent->Real; - return tmp; - case SS_DATATYPE_OBJECT: - tmp->Type = SS_DATATYPE_OBJECT; - tmp->Object = Ent->Object; - return tmp; - case ET_FUNCTION_START: - AST_RuntimeError(NULL, "_GetSpiderValue on ET_FUNCTION_START"); - return NULL; - default: - SpiderScript_ReferenceValue(Ent->Reference); - return Ent->Reference; - } -} - -void Bytecode_int_SetSpiderValue(tBC_StackEnt *Ent, tSpiderValue *Value) -{ - if(!Value) { - Ent->Type = ET_REFERENCE; - Ent->Reference = NULL; - return ; - } - switch(Value->Type) - { - case SS_DATATYPE_INTEGER: - Ent->Type = SS_DATATYPE_INTEGER; - Ent->Integer = Value->Integer; - break; - case SS_DATATYPE_REAL: - Ent->Type = SS_DATATYPE_REAL; - Ent->Real = Value->Real; - break; - case SS_DATATYPE_OBJECT: - Ent->Type = SS_DATATYPE_OBJECT; - Ent->Object = Value->Object; - Ent->Object->ReferenceCount ++; - break; - default: - SpiderScript_ReferenceValue(Value); - Ent->Type = ET_REFERENCE; - Ent->Reference = Value; - break; - } -} - -void Bytecode_int_DerefStackValue(tBC_StackEnt *Ent) -{ - switch(Ent->Type) - { - case SS_DATATYPE_INTEGER: - case SS_DATATYPE_REAL: - break; - case SS_DATATYPE_OBJECT: - if(Ent->Object) { - Ent->Object->ReferenceCount --; - if(Ent->Object->ReferenceCount == 0) { - Ent->Object->Type->Destructor( Ent->Object ); - } -// printf("Object %p derefed (obj refcount = %i)\n", Ent->Object, Ent->Object->ReferenceCount); - } - Ent->Object = NULL; - break; - default: - if(Ent->Reference) - SpiderScript_DereferenceValue(Ent->Reference); - Ent->Reference = NULL; - break; - } -} -void Bytecode_int_RefStackValue(tBC_StackEnt *Ent) -{ - switch(Ent->Type) - { - case SS_DATATYPE_INTEGER: - case SS_DATATYPE_REAL: - break; - case SS_DATATYPE_OBJECT: - if(Ent->Object) { - Ent->Object->ReferenceCount ++; -// printf("Object %p referenced (count = %i)\n", Ent->Object, Ent->Object->ReferenceCount); - } - break; - default: - if(Ent->Reference) - SpiderScript_ReferenceValue(Ent->Reference); - break; - } -} - -void Bytecode_int_PrintStackValue(tBC_StackEnt *Ent) -{ - switch(Ent->Type) - { - case SS_DATATYPE_INTEGER: - printf("0x%"PRIx64, Ent->Integer); - break; - case SS_DATATYPE_REAL: - printf("%lf", Ent->Real); - break; - case SS_DATATYPE_OBJECT: - printf("Obj %p", Ent->Object); - break; - default: - printf("*%p", Ent->Reference); - break; - } -} - -#if TRACE -# define PRINT_STACKVAL(val) Bytecode_int_PrintStackValue(&val) -#else -# define PRINT_STACKVAL(val) -#endif - -#define GET_STACKVAL(dst) if((ret = Bytecode_int_StackPop(Stack, &dst))) { \ - AST_RuntimeError(NULL, "Stack pop failed, empty stack");\ - return ret; \ -} -#define PUT_STACKVAL(src) if((ret = Bytecode_int_StackPush(Stack, &src))) { \ - AST_RuntimeError(NULL, "Stack push failed, full stack");\ - return ret; \ -} -#define OP_INDX(op_ptr) ((op_ptr)->Content.StringInt.Integer) -#define OP_STRING(op_ptr) ((op_ptr)->Content.StringInt.String) - -tSpiderValue *Bytecode_ExecuteFunction(tSpiderScript *Script, tScript_Function *Fcn, int NArguments, tSpiderValue **Args) -{ - const int stack_size = 100; - tSpiderValue *ret, tmpsval; - tBC_Stack *stack; - tBC_StackEnt val; - int i; - - stack = malloc(sizeof(tBC_Stack) + stack_size*sizeof(tBC_StackEnt)); - stack->EntrySpace = stack_size; - stack->EntryCount = 0; - - // Push arguments in order (so top is last arg) - for( i = 0; i < NArguments; i ++ ) - { - Bytecode_int_SetSpiderValue(&val, Args[i]); - Bytecode_int_StackPush(stack, &val); - } - - // Call - Bytecode_int_ExecuteFunction(Script, Fcn, stack, NArguments); - - // Get return value - if( Bytecode_int_StackPop(stack, &val) ) { - free(stack); - return NULL; - } - free(stack); - ret = Bytecode_int_GetSpiderValue(&val, &tmpsval); - // Ensure it's a heap value - if(ret == &tmpsval) { - ret = malloc(sizeof(tSpiderValue)); - memcpy(ret, &tmpsval, sizeof(tSpiderValue)); - } - - return ret; -} - -tSpiderNamespace *Bytecode_int_ResolveNamespace(tSpiderNamespace *Start, const char *Name, const char **FinalName) -{ - char *pos; - tSpiderNamespace *ns = Start; - while( (pos = strchr(Name, BC_NS_SEPARATOR)) ) - { - int len = pos - Name; - for( ns = ns->FirstChild; ns; ns = ns->Next ) - { - if(memcmp(ns->Name, Name, len) == 0 && ns->Name[len] == 0) - break; - } - if(!ns) { - return NULL; - } - Name += len + 1; - } - if(FinalName) *FinalName = Name; - return ns; -} - -#define STATE_HDR() DEBUG_F("%p %2i ", op, Stack->EntryCount) - -/** - * \brief Execute a bytecode function with a stack - */ -int Bytecode_int_ExecuteFunction(tSpiderScript *Script, tScript_Function *Fcn, tBC_Stack *Stack, int ArgCount) -{ - int ret, ast_op, i; - tBC_Op *op; - tBC_StackEnt val1, val2; - int local_var_count = Fcn->BCFcn->MaxVariableCount; - tBC_StackEnt local_vars[local_var_count]; // Includes arguments - tSpiderValue tmpVal1, tmpVal2; // temp storage - tSpiderValue *pval1, *pval2, *ret_val; - tSpiderNamespace *default_namespace = &Script->Variant->RootNamespace; - - // Initialise local vars - for( i = 0; i < local_var_count; i ++ ) - local_vars[i].Type = ET_NULL; - - // Pop off arguments - if( ArgCount > Fcn->ArgumentCount ) return -1; - DEBUG_F("Fcn->ArgumentCount = %i\n", Fcn->ArgumentCount); - for( i = Fcn->ArgumentCount; i > ArgCount; ) - { - i --; - local_vars[i].Integer = 0; - local_vars[i].Type = Fcn->Arguments[i].Type; - } - for( ; i --; ) - { - GET_STACKVAL(local_vars[i]); - // TODO: Type checks / enforcing - } - - // Mark the start - memset(&val1, 0, sizeof(val1)); - val1.Type = ET_FUNCTION_START; - PUT_STACKVAL(val1); - - // Execute! - op = Fcn->BCFcn->Operations; - while(op) - { - const char *opstr = ""; - tBC_Op *nextop = op->Next, *jmp_target; - ast_op = 0; - switch(op->Operation) - { - case BC_OP_NOP: - STATE_HDR(); - DEBUG_F("NOP\n"); - break; - // Jumps - case BC_OP_JUMP: - STATE_HDR(); - // NOTE: Evil, all jumps are off by -1, so fix that - jmp_target = Fcn->BCFcn->Labels[ OP_INDX(op) ]->Next; - DEBUG_F("JUMP #%i %p\n", OP_INDX(op), jmp_target); - nextop = jmp_target; - break; - case BC_OP_JUMPIF: - STATE_HDR(); - jmp_target = Fcn->BCFcn->Labels[ OP_INDX(op) ]->Next; - DEBUG_F("JUMPIF #%i %p\n", OP_INDX(op), jmp_target); - GET_STACKVAL(val1); - if( Bytecode_int_IsStackEntTrue(&val1) ) - nextop = jmp_target; - break; - case BC_OP_JUMPIFNOT: - STATE_HDR(); - jmp_target = Fcn->BCFcn->Labels[ OP_INDX(op) ]->Next; - DEBUG_F("JUMPIFNOT #%i %p\n", OP_INDX(op), jmp_target); - GET_STACKVAL(val1); - if( !Bytecode_int_IsStackEntTrue(&val1) ) - nextop = jmp_target; - break; - - // Define variables - case BC_OP_DEFINEVAR: { - int type, slot; - type = OP_INDX(op) & 0xFFFF; - slot = OP_INDX(op) >> 16; - if(slot < 0 || slot >= local_var_count) { - DEBUG_F("ERROR: slot %i out of range (max %i)\n", slot, local_var_count); - return -1; - } - STATE_HDR(); - DEBUG_F("DEFVAR %i of type %i\n", slot, type); - if( local_vars[slot].Type != ET_NULL ) { - Bytecode_int_DerefStackValue( &local_vars[slot] ); - local_vars[slot].Type = ET_NULL; - } - memset(&local_vars[slot], 0, sizeof(local_vars[0])); - local_vars[slot].Type = type; - } break; - - // Enter/Leave context - // - NOP now - case BC_OP_ENTERCONTEXT: - STATE_HDR(); - DEBUG_F("ENTERCONTEXT\n"); - break; - case BC_OP_LEAVECONTEXT: - STATE_HDR(); - DEBUG_F("LEAVECONTEXT\n"); - break; - - // Variables - case BC_OP_LOADVAR: { - int slot = OP_INDX(op); - STATE_HDR(); - DEBUG_F("LOADVAR %i ", slot); - if( slot < 0 || slot >= local_var_count ) { - AST_RuntimeError(NULL, "Loading from invalid slot %i", slot); - return -1; - } - DEBUG_F("("); PRINT_STACKVAL(local_vars[slot]); DEBUG_F(")\n"); - PUT_STACKVAL(local_vars[slot]); - Bytecode_int_RefStackValue( &local_vars[slot] ); - } break; - case BC_OP_SAVEVAR: { - int slot = OP_INDX(op); - STATE_HDR(); - DEBUG_F("SAVEVAR %i = ", slot); - if( slot < 0 || slot >= local_var_count ) { - AST_RuntimeError(NULL, "Loading from invalid slot %i", slot); - return -1; - } - DEBUG_F("[Deref "); PRINT_STACKVAL(local_vars[slot]); DEBUG_F("] "); - Bytecode_int_DerefStackValue( &local_vars[slot] ); - GET_STACKVAL(local_vars[slot]); - PRINT_STACKVAL(local_vars[slot]); - DEBUG_F("\n"); - } break; - - // Constants: - case BC_OP_LOADINT: - STATE_HDR(); - DEBUG_F("LOADINT 0x%lx\n", op->Content.Integer); - val1.Type = SS_DATATYPE_INTEGER; - val1.Integer = op->Content.Integer; - PUT_STACKVAL(val1); - break; - case BC_OP_LOADREAL: - STATE_HDR(); - DEBUG_F("LOADREAL %lf\n", op->Content.Real); - val1.Type = SS_DATATYPE_REAL; - val1.Real = op->Content.Real; - PUT_STACKVAL(val1); - break; - case BC_OP_LOADSTR: - STATE_HDR(); - DEBUG_F("LOADSTR %i \"%s\"\n", OP_INDX(op), OP_STRING(op)); - val1.Type = SS_DATATYPE_STRING; - val1.Reference = SpiderScript_CreateString(OP_INDX(op), OP_STRING(op)); - PUT_STACKVAL(val1); - break; - - case BC_OP_CAST: - STATE_HDR(); - val2.Type = OP_INDX(op); - DEBUG_F("CAST to %i\n", val2.Type); - GET_STACKVAL(val1); - if(val1.Type == val2.Type) { - PUT_STACKVAL(val1); - break; - } - switch(val2.Type * 100 + val1.Type ) - { - case SS_DATATYPE_INTEGER*100 + SS_DATATYPE_REAL: - val2.Integer = val1.Real; - PUT_STACKVAL(val2); - break; - case SS_DATATYPE_REAL*100 + SS_DATATYPE_INTEGER: - val2.Real = val1.Integer; - PUT_STACKVAL(val2); - break; - default: { - pval1 = Bytecode_int_GetSpiderValue(&val1, &tmpVal1); - pval2 = SpiderScript_CastValueTo(val2.Type, pval1); - if(pval1 != &tmpVal1) SpiderScript_DereferenceValue(pval1); - Bytecode_int_SetSpiderValue(&val2, pval2); - SpiderScript_DereferenceValue(pval2); - PUT_STACKVAL(val2); - } break; - } - break; - - case BC_OP_DUPSTACK: - STATE_HDR(); - DEBUG_F("DUPSTACK "); - GET_STACKVAL(val1); - PRINT_STACKVAL(val1); - DEBUG_F("\n"); - PUT_STACKVAL(val1); - PUT_STACKVAL(val1); - Bytecode_int_RefStackValue(&val1); - break; - - // Discard the top item from the stack - case BC_OP_DELSTACK: - STATE_HDR(); - DEBUG_F("DELSTACK\n"); - GET_STACKVAL(val1); - break; - - // Unary Operations - case BC_OP_LOGICNOT: - STATE_HDR(); - DEBUG_F("LOGICNOT\n"); - - GET_STACKVAL(val1); - val2.Type = SS_DATATYPE_INTEGER; - val2.Integer = !Bytecode_int_IsStackEntTrue(&val1); - Bytecode_int_StackPush(Stack, &val2); - Bytecode_int_DerefStackValue(&val1); - break; - case BC_OP_BITNOT: - if(!ast_op) ast_op = NODETYPE_BWNOT; - - STATE_HDR(); - DEBUG_F("UNIOP %i\n", ast_op); - - GET_STACKVAL(val1); - pval1 = Bytecode_int_GetSpiderValue(&val1, &tmpVal1); - Bytecode_int_DerefStackValue(&val1); - - ret_val = AST_ExecuteNode_UniOp(Script, NULL, ast_op, pval1); - if(pval1 != &tmpVal1) SpiderScript_DereferenceValue(pval1); - Bytecode_int_SetSpiderValue(&val1, ret_val); - if(ret_val != &tmpVal1) SpiderScript_DereferenceValue(ret_val); - Bytecode_int_StackPush(Stack, &val1); - - break; - - // Binary Operations - case BC_OP_LOGICAND: - if(!ast_op) ast_op = NODETYPE_LOGICALAND, opstr = "LOGICAND"; - case BC_OP_LOGICOR: - if(!ast_op) ast_op = NODETYPE_LOGICALOR, opstr = "LOGICOR"; - case BC_OP_LOGICXOR: - if(!ast_op) ast_op = NODETYPE_LOGICALXOR, opstr = "LOGICXOR"; - - STATE_HDR(); - DEBUG_F("%s\n", opstr); - - GET_STACKVAL(val1); - GET_STACKVAL(val2); - - switch(op->Operation) - { - case BC_OP_LOGICAND: - i = Bytecode_int_IsStackEntTrue(&val1) && Bytecode_int_IsStackEntTrue(&val2); - break; - case BC_OP_LOGICOR: - i = Bytecode_int_IsStackEntTrue(&val1) || Bytecode_int_IsStackEntTrue(&val2); - break; - case BC_OP_LOGICXOR: - i = Bytecode_int_IsStackEntTrue(&val1) ^ Bytecode_int_IsStackEntTrue(&val2); - break; - } - Bytecode_int_DerefStackValue(&val1); - Bytecode_int_DerefStackValue(&val2); - - val1.Type = SS_DATATYPE_INTEGER; - val1.Integer = i; - Bytecode_int_StackPush(Stack, &val1); - break; - - case BC_OP_BITAND: - if(!ast_op) ast_op = NODETYPE_BWAND, opstr = "BITAND"; - case BC_OP_BITOR: - if(!ast_op) ast_op = NODETYPE_BWOR, opstr = "BITOR"; - case BC_OP_BITXOR: - if(!ast_op) ast_op = NODETYPE_BWXOR, opstr = "BITXOR"; - - case BC_OP_BITSHIFTLEFT: - if(!ast_op) ast_op = NODETYPE_BITSHIFTLEFT, opstr = "BITSHIFTLEFT"; - case BC_OP_BITSHIFTRIGHT: - if(!ast_op) ast_op = NODETYPE_BITSHIFTRIGHT, opstr = "BITSHIFTRIGHT"; - case BC_OP_BITROTATELEFT: - if(!ast_op) ast_op = NODETYPE_BITROTATELEFT, opstr = "BITROTATELEFT"; - - case BC_OP_ADD: - if(!ast_op) ast_op = NODETYPE_ADD, opstr = "ADD"; - case BC_OP_SUBTRACT: - if(!ast_op) ast_op = NODETYPE_SUBTRACT, opstr = "SUBTRACT"; - case BC_OP_MULTIPLY: - if(!ast_op) ast_op = NODETYPE_MULTIPLY, opstr = "MULTIPLY"; - case BC_OP_DIVIDE: - if(!ast_op) ast_op = NODETYPE_DIVIDE, opstr = "DIVIDE"; - case BC_OP_MODULO: - if(!ast_op) ast_op = NODETYPE_MODULO, opstr = "MODULO"; - - case BC_OP_EQUALS: - if(!ast_op) ast_op = NODETYPE_EQUALS, opstr = "EQUALS"; - case BC_OP_LESSTHAN: - if(!ast_op) ast_op = NODETYPE_LESSTHAN, opstr = "LESSTHAN"; - case BC_OP_LESSTHANOREQUAL: - if(!ast_op) ast_op = NODETYPE_LESSTHANEQUAL, opstr = "LESSTHANOREQUAL"; - case BC_OP_GREATERTHAN: - if(!ast_op) ast_op = NODETYPE_GREATERTHAN, opstr = "GREATERTHAN"; - case BC_OP_GREATERTHANOREQUAL: - if(!ast_op) ast_op = NODETYPE_GREATERTHANEQUAL, opstr = "GREATERTHANOREQUAL"; - - STATE_HDR(); - DEBUG_F("BINOP %i %s (bc %i)\n", ast_op, opstr, op->Operation); - - GET_STACKVAL(val2); // Right - GET_STACKVAL(val1); // Left - - #define PERFORM_NUM_OP(_type, _field) if(val1.Type == _type && val1.Type == val2.Type) { \ - switch(op->Operation) { \ - case BC_OP_ADD: val1._field = val1._field + val2._field; break; \ - case BC_OP_SUBTRACT: val1._field = val1._field - val2._field; break; \ - case BC_OP_MULTIPLY: val1._field = val1._field * val2._field; break; \ - case BC_OP_DIVIDE: val1._field = val1._field / val2._field; break; \ - case BC_OP_EQUALS: val1._field = val1._field == val2._field; break; \ - case BC_OP_LESSTHAN: val1._field = val1._field < val2._field; break; \ - case BC_OP_LESSTHANOREQUAL: val1._field = val1._field <= val2._field; break; \ - case BC_OP_GREATERTHAN: val1._field = val1._field > val2._field; break; \ - case BC_OP_GREATERTHANOREQUAL: val1._field = val1._field >= val2._field; break; \ - \ - case BC_OP_BITAND: val1._field = (int64_t)val1._field & (int64_t)val2._field; break; \ - case BC_OP_BITOR: val1._field = (int64_t)val1._field | (int64_t)val2._field; break; \ - case BC_OP_BITXOR: val1._field = (int64_t)val1._field ^ (int64_t)val2._field; break; \ - case BC_OP_MODULO: val1._field = (int64_t)val1._field % (int64_t)val2._field; break; \ - default: AST_RuntimeError(NULL, "Invalid operation on datatype %i", _type); nextop = NULL; break;\ - }\ - PUT_STACKVAL(val1);\ - break;\ - } - - PERFORM_NUM_OP(SS_DATATYPE_INTEGER, Integer); - PERFORM_NUM_OP(SS_DATATYPE_REAL, Real); - - pval1 = Bytecode_int_GetSpiderValue(&val1, &tmpVal1); - pval2 = Bytecode_int_GetSpiderValue(&val2, &tmpVal2); - Bytecode_int_DerefStackValue(&val1); - Bytecode_int_DerefStackValue(&val2); - - ret_val = AST_ExecuteNode_BinOp(Script, NULL, ast_op, pval1, pval2); - if(pval1 != &tmpVal1) SpiderScript_DereferenceValue(pval1); - if(pval2 != &tmpVal2) SpiderScript_DereferenceValue(pval2); - - if(ret_val == ERRPTR) { - AST_RuntimeError(NULL, "_BinOp returned ERRPTR"); - nextop = NULL; - break; - } - Bytecode_int_SetSpiderValue(&val1, ret_val); - if(ret_val != &tmpVal1) SpiderScript_DereferenceValue(ret_val); - PUT_STACKVAL(val1); - break; - - // Functions etc - case BC_OP_CREATEOBJ: - case BC_OP_CALLFUNCTION: - case BC_OP_CALLMETHOD: { - tScript_Function *fcn = NULL; - const char *name = OP_STRING(op); - int arg_count = OP_INDX(op); - - STATE_HDR(); - DEBUG_F("CALL FUNCTION %s %i args\n", name, arg_count); - - if( op->Operation == BC_OP_CALLFUNCTION ) - { - // Check current script functions (for fast call) - for(fcn = Script->Functions; fcn; fcn = fcn->Next) - { - if(strcmp(name, fcn->Name) == 0) { - break; - } - } - if(fcn && fcn->BCFcn) - { - DEBUG_F(" - Fast call\n"); - Bytecode_int_ExecuteFunction(Script, fcn, Stack, arg_count); - break; - } - } - - // Slower call - { - tSpiderNamespace *ns = NULL; - tSpiderValue *args[arg_count]; - tSpiderValue *rv; - // Read arguments - for( i = arg_count; i --; ) - { - GET_STACKVAL(val1); - args[i] = Bytecode_int_GetSpiderValue(&val1, NULL); - Bytecode_int_DerefStackValue(&val1); - } - - // Resolve namespace into pointer - if( op->Operation != BC_OP_CALLMETHOD ) { - if( name[0] == BC_NS_SEPARATOR ) { - name ++; - ns = Bytecode_int_ResolveNamespace(&Script->Variant->RootNamespace, name, &name); - } - else { - // TODO: Support multiple default namespaces - ns = Bytecode_int_ResolveNamespace(default_namespace, name, &name); - } - } - - // Call the function etc. - if( op->Operation == BC_OP_CALLFUNCTION ) - { - rv = SpiderScript_ExecuteFunction(Script, ns, name, arg_count, args); - } - else if( op->Operation == BC_OP_CREATEOBJ ) - { - rv = SpiderScript_CreateObject(Script, ns, name, arg_count, args); - } - else if( op->Operation == BC_OP_CALLMETHOD ) - { - tSpiderObject *obj; - GET_STACKVAL(val1); - - if(val1.Type == SS_DATATYPE_OBJECT) - obj = val1.Object; - else if(val1.Type == ET_REFERENCE && val1.Reference->Type == SS_DATATYPE_OBJECT) - obj = val1.Reference->Object; - else { - // Error - AST_RuntimeError(NULL, "OP_CALLMETHOD on non object"); - nextop = NULL; - break; - } - rv = SpiderScript_ExecuteMethod(Script, obj, name, arg_count, args); - Bytecode_int_DerefStackValue(&val1); - } - else - { - AST_RuntimeError(NULL, "BUG - Unknown operation for CALL/CREATEOBJ (%i)", op->Operation); - rv = ERRPTR; - } - if(rv == ERRPTR) { - AST_RuntimeError(NULL, "SpiderScript_ExecuteFunction returned ERRPTR"); - nextop = NULL; - break; - } - // Clean up args - for( i = arg_count; i --; ) - SpiderScript_DereferenceValue(args[i]); - // Get and push return - Bytecode_int_SetSpiderValue(&val1, rv); - PUT_STACKVAL(val1); - // Deref return - SpiderScript_DereferenceValue(rv); - } - } break; - - case BC_OP_RETURN: - STATE_HDR(); - DEBUG_F("RETURN\n"); - nextop = NULL; - break; - - default: - // TODO: - STATE_HDR(); - AST_RuntimeError(NULL, "Unknown operation %i\n", op->Operation); - nextop = NULL; - break; - } - op = nextop; - } - - // Clean up - // - Delete local vars - for( i = 0; i < local_var_count; i ++ ) - { - if( local_vars[i].Type != ET_NULL ) - { - Bytecode_int_DerefStackValue(&local_vars[i]); - } - } - - // - Restore stack -// printf("TODO: Roll back stack\n"); - if( Stack->Entries[Stack->EntryCount - 1].Type == ET_FUNCTION_START ) - Stack->EntryCount --; - else - { - GET_STACKVAL(val1); - while( Stack->EntryCount && Stack->Entries[ --Stack->EntryCount ].Type != ET_FUNCTION_START ) - { - Bytecode_int_DerefStackValue( &Stack->Entries[Stack->EntryCount] ); - } - PUT_STACKVAL(val1); - } - - - return 0; -} - diff --git a/Usermode/Libraries/libspiderscript.so_src/exports.c b/Usermode/Libraries/libspiderscript.so_src/exports.c deleted file mode 100644 index 4c73eb9f..00000000 --- a/Usermode/Libraries/libspiderscript.so_src/exports.c +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Acess2 - SpiderScript - * - Script Exports (Lang. Namespace) - */ -#include -#include -#include -#include - -// === PROTOTYPES === -tSpiderValue *Exports_Lang_Struct(tSpiderScript *Script, int NArgs, tSpiderValue **Args); - -// === GLOBALS === -tSpiderFunction gExports_Lang_Struct = {NULL,"Lang.Struct", Exports_Lang_Struct, {SS_DATATYPE_STRING,-1}}; -tSpiderFunction *gpExports_First = &gExports_Lang_Struct; - -// === CODE === -tSpiderValue *Exports_Lang_Struct(tSpiderScript *Script, int NArgs, tSpiderValue **Args) -{ - int i; - printf("Exports_Lang_Struct: (Script=%p, NArgs=%i, Args=%p)\n", Script, NArgs, Args); - - for( i = 0; i < NArgs; i ++ ) - { - printf(" Args[%i] = {Type: %i, ", i, Args[i]->Type); - switch(Args[i]->Type) - { - case SS_DATATYPE_INTEGER: - printf(" Integer: 0x%lx", Args[i]->Integer); - break; - case SS_DATATYPE_REAL: - printf(" Real: %f", Args[i]->Real); - break; - case SS_DATATYPE_STRING: - printf(" Length: %i, Data = '%s'", Args[i]->String.Length, Args[i]->String.Data); - break; - default: - break; - } - printf("}\n"); - } - - return NULL; -} diff --git a/Usermode/Libraries/libspiderscript.so_src/lex.c b/Usermode/Libraries/libspiderscript.so_src/lex.c deleted file mode 100644 index 2d16bcfb..00000000 --- a/Usermode/Libraries/libspiderscript.so_src/lex.c +++ /dev/null @@ -1,468 +0,0 @@ -/* - * SpiderScript - * - Script Lexer - */ -#include "tokens.h" -#include -#include -#include - -#define DEBUG 0 - -#define ARRAY_SIZE(x) ((sizeof(x))/(sizeof((x)[0]))) - -// === PROTOTYPES === - int is_ident(char ch); - int isdigit(int ch); - int isspace(int ch); - int GetToken(tParser *File); - -// === CONSTANTS === -const struct { - const int Value; - const char *Name; -} csaReservedWords[] = { - {TOK_RWD_FUNCTION, "function"}, - - {TOK_RWD_RETURN, "return"}, - {TOK_RWD_BREAK, "break"}, - {TOK_RWD_CONTINUE, "continue"}, - {TOK_RWD_NEW, "new"}, - - {TOK_RWD_IF, "if"}, - {TOK_RWD_ELSE, "else"}, - {TOK_RWD_DO, "do"}, - {TOK_RWD_WHILE, "while"}, - {TOK_RWD_FOR, "for"}, - - {TOK_RWD_NULL, "null"}, - {TOK_RWD_VOID, "void"}, - {TOK_RWD_OBJECT, "Object"}, - {TOK_RWD_OPAQUE, "Opaque"}, - {TOK_RWD_INTEGER, "Integer"}, - {TOK_RWD_REAL, "Real"}, - {TOK_RWD_STRING, "String"} -}; - -// === CODE === -/** - * \brief Read a token from a buffer - * \param File Parser state - */ -int GetToken(tParser *File) -{ - int ret; - - if( File->NextToken != -1 ) { - // Save Last - File->LastToken = File->Token; - File->LastTokenStr = File->TokenStr; - File->LastTokenLen = File->TokenLen; - File->LastLine = File->CurLine; - // Restore Next - File->Token = File->NextToken; - File->TokenStr = File->NextTokenStr; - File->TokenLen = File->NextTokenLen; - File->CurLine = File->NextLine; - // Set State - File->CurPos = File->TokenStr + File->TokenLen; - File->NextToken = -1; - { - char buf[ File->TokenLen + 1]; - memcpy(buf, File->TokenStr, File->TokenLen); - buf[File->TokenLen] = 0; - #if DEBUG - printf(" GetToken: FAST Return %i (%i long) (%s)\n", File->Token, File->TokenLen, buf); - #endif - } - return File->Token; - } - - //printf(" GetToken: File=%p, File->CurPos = %p\n", File, File->CurPos); - - // Clear whitespace (including comments) - for( ;; ) - { - // Whitespace - while( isspace( *File->CurPos ) ) - { - //printf("whitespace 0x%x, line = %i\n", *File->CurPos, File->CurLine); - if( *File->CurPos == '\n' ) - File->CurLine ++; - File->CurPos ++; - } - - // # Line Comments - if( *File->CurPos == '#' ) { - while( *File->CurPos && *File->CurPos != '\n' ) - File->CurPos ++; - continue ; - } - - // C-Style Line Comments - if( *File->CurPos == '/' && File->CurPos[1] == '/' ) { - while( *File->CurPos && *File->CurPos != '\n' ) - File->CurPos ++; - continue ; - } - - // C-Style Block Comments - if( *File->CurPos == '/' && File->CurPos[1] == '*' ) { - File->CurPos += 2; // Eat the '/*' - while( *File->CurPos && !(File->CurPos[-1] == '*' && *File->CurPos == '/') ) - { - if( *File->CurPos == '\n' ) File->CurLine ++; - File->CurPos ++; - } - File->CurPos ++; // Eat the '/' - continue ; - } - - // No more "whitespace" - break; - } - - // Save previous tokens (speeds up PutBack and LookAhead) - File->LastToken = File->Token; - File->LastTokenStr = File->TokenStr; - File->LastTokenLen = File->TokenLen; - File->LastLine = File->CurLine; - - // Read token - File->TokenStr = File->CurPos; - switch( *File->CurPos++ ) - { - case '\0': ret = TOK_EOF; break; - - // Operations - case '^': - if( *File->CurPos == '^' ) { - File->CurPos ++; - ret = TOK_LOGICXOR; - break; - } - ret = TOK_XOR; - break; - - case '|': - if( *File->CurPos == '|' ) { - File->CurPos ++; - ret = TOK_LOGICOR; - break; - } - ret = TOK_OR; - break; - - case '&': - if( *File->CurPos == '&' ) { - File->CurPos ++; - ret = TOK_LOGICAND; - break; - } - ret = TOK_AND; - break; - - case '/': - if( *File->CurPos == '=' ) { - File->CurPos ++; - ret = TOK_ASSIGN_DIV; - break; - } - ret = TOK_DIV; - break; - case '*': - if( *File->CurPos == '=' ) { - File->CurPos ++; - ret = TOK_ASSIGN_MUL; - break; - } - ret = TOK_MUL; - break; - case '+': - if( *File->CurPos == '+' ) { - File->CurPos ++; - ret = TOK_INCREMENT; - break; - } - if( *File->CurPos == '=' ) { - File->CurPos ++; - ret = TOK_ASSIGN_PLUS; - break; - } - ret = TOK_PLUS; - break; - case '-': - if( *File->CurPos == '-' ) { - File->CurPos ++; - ret = TOK_DECREMENT; - break; - } - if( *File->CurPos == '=' ) { - File->CurPos ++; - ret = TOK_ASSIGN_MINUS; - break; - } - if( *File->CurPos == '>' ) { - File->CurPos ++; - ret = TOK_ELEMENT; - break; - } - ret = TOK_MINUS; - break; - - // Strings - case '"': - while( *File->CurPos && !(*File->CurPos == '"' && *File->CurPos != '\\') ) - File->CurPos ++; - if( *File->CurPos ) - { - File->CurPos ++; - ret = TOK_STR; - } - else - ret = TOK_EOF; - break; - - // Brackets - case '(': ret = TOK_PAREN_OPEN; break; - case ')': ret = TOK_PAREN_CLOSE; break; - case '{': ret = TOK_BRACE_OPEN; break; - case '}': ret = TOK_BRACE_CLOSE; break; - case '[': ret = TOK_SQUARE_OPEN; break; - case ']': ret = TOK_SQUARE_CLOSE; break; - - // Core symbols - case ';': ret = TOK_SEMICOLON; break; - case ',': ret = TOK_COMMA; break; - #if USE_SCOPE_CHAR - case '.': ret = TOK_SCOPE; break; - #endif - - // Equals - case '=': - // Comparison Equals - if( *File->CurPos == '=' ) { - File->CurPos ++; - ret = TOK_EQUALS; - break; - } - // Assignment Equals - ret = TOK_ASSIGN; - break; - - // Less-Than - case '<': - // Less-Than or Equal - if( *File->CurPos == '=' ) { - File->CurPos ++; - ret = TOK_LTE; - break; - } - ret = TOK_LT; - break; - - // Greater-Than - case '>': - // Greater-Than or Equal - if( *File->CurPos == '=' ) { - File->CurPos ++; - ret = TOK_GTE; - break; - } - ret = TOK_GT; - break; - - // Logical NOT - case '!': - ret = TOK_LOGICNOT; - break; - // Bitwise NOT - case '~': - ret = TOK_BWNOT; - break; - - // Variables - // \$[0-9]+ or \$[_a-zA-Z][_a-zA-Z0-9]* - case '$': - // Numeric Variable - if( isdigit( *File->CurPos ) ) { - while( isdigit(*File->CurPos) ) - File->CurPos ++; - } - // Ident Variable - else { - while( is_ident(*File->CurPos) || isdigit(*File->CurPos) ) - File->CurPos ++; - } - ret = TOK_VARIABLE; - break; - - // Default (Numbers and Identifiers) - default: - File->CurPos --; - - // Numbers - if( isdigit(*File->CurPos) ) - { - ret = TOK_INTEGER; - if( *File->CurPos == '0' && File->CurPos[1] == 'x' ) - { - File->CurPos += 2; - while(('0' <= *File->CurPos && *File->CurPos <= '9') - || ('A' <= *File->CurPos && *File->CurPos <= 'F') - || ('a' <= *File->CurPos && *File->CurPos <= 'f') ) - { - File->CurPos ++; - } - } - else - { - while( isdigit(*File->CurPos) ) - File->CurPos ++; - -// printf("*File->CurPos = '%c'\n", *File->CurPos); - - // Decimal - if( *File->CurPos == '.' ) - { - ret = TOK_REAL; - File->CurPos ++; - while( isdigit(*File->CurPos) ) - File->CurPos ++; - } - // Exponent - if( *File->CurPos == 'e' || *File->CurPos == 'E' ) - { - ret = TOK_REAL; - File->CurPos ++; - if(*File->CurPos == '-' || *File->CurPos == '+') - File->CurPos ++; - while( isdigit(*File->CurPos) ) - File->CurPos ++; - } - -// printf(" ret = %i\n", ret); - } - break; - } - - // Identifier - if( is_ident(*File->CurPos) ) - { - ret = TOK_IDENT; - - // Identifier - while( is_ident(*File->CurPos) || isdigit(*File->CurPos) ) - File->CurPos ++; - - // This is set later too, but we use it below - File->TokenLen = File->CurPos - File->TokenStr; - - // Check if it's a reserved word - { - char buf[File->TokenLen + 1]; - int i; - memcpy(buf, File->TokenStr, File->TokenLen); - buf[File->TokenLen] = 0; - for( i = 0; i < ARRAY_SIZE(csaReservedWords); i ++ ) - { - if(strcmp(csaReservedWords[i].Name, buf) == 0) { - ret = csaReservedWords[i].Value; - break ; - } - } - } - // If there's no match, just keep ret as TOK_IDENT - - break; - } - // Syntax Error - File->Token = TOK_INVAL; - - fprintf(stderr, "Syntax Error: Unknown symbol '%c'\n", *File->CurPos); - longjmp(File->JmpTarget, 1); - - break; - } - // Return - File->Token = ret; - File->TokenLen = File->CurPos - File->TokenStr; - - #if DEBUG - { - char buf[ File->TokenLen + 1]; - memcpy(buf, File->TokenStr, File->TokenLen); - buf[File->TokenLen] = 0; - //printf(" GetToken: File->CurPos = %p\n", File->CurPos); - printf(" GetToken: Return %i (%i long) (%s)\n", ret, File->TokenLen, buf); - } - #endif - return ret; -} - -void PutBack(tParser *File) -{ - if( File->LastToken == -1 ) { - // ERROR: - fprintf(stderr, "INTERNAL ERROR: Putback when LastToken==-1\n"); - longjmp( File->JmpTarget, -1 ); - return ; - } - #if DEBUG - printf(" PutBack: Was on %i\n", File->Token); - #endif - // Save - File->NextLine = File->CurLine; - File->NextToken = File->Token; - File->NextTokenStr = File->TokenStr; - File->NextTokenLen = File->TokenLen; - // Restore - File->CurLine = File->LastLine; - File->Token = File->LastToken; - File->TokenStr = File->LastTokenStr; - File->TokenLen = File->LastTokenLen; - File->CurPos = File->NextTokenStr; - // Invalidate - File->LastToken = -1; -} - -int LookAhead(tParser *File) -{ - // TODO: Should I save the entire state here? - int ret = GetToken(File); - PutBack(File); - return ret; -} - -// --- Helpers --- -/** - * \brief Check for ident characters - * \note Matches Regex [a-zA-Z_] - */ -int is_ident(char ch) -{ - if('a' <= ch && ch <= 'z') return 1; - if('A' <= ch && ch <= 'Z') return 1; - if(ch == '_') return 1; - #if !USE_SCOPE_CHAR - if(ch == '.') return 1; - #endif - if(ch < 0) return 1; - return 0; -} - -int isdigit(int ch) -{ - if('0' <= ch && ch <= '9') return 1; - return 0; -} - -int isspace(int ch) -{ - if(' ' == ch) return 1; - if('\t' == ch) return 1; - if('\b' == ch) return 1; - if('\n' == ch) return 1; - if('\r' == ch) return 1; - return 0; -} diff --git a/Usermode/Libraries/libspiderscript.so_src/main.c b/Usermode/Libraries/libspiderscript.so_src/main.c deleted file mode 100644 index bd292805..00000000 --- a/Usermode/Libraries/libspiderscript.so_src/main.c +++ /dev/null @@ -1,145 +0,0 @@ -/* - * Acess2 - SpiderScript - * Interpreter Library - */ -#include -#include -#include -#include -#include "common.h" -#include "ast.h" -#include "bytecode_gen.h" - -// === IMPORTS === -extern int Parse_Buffer(tSpiderScript *Script, const char *Buffer, const char *Filename); -extern tAST_Variable *Variable_Define(tAST_BlockState *Block, int Type, const char *Name); -extern void Variable_SetValue(tAST_BlockState *Block, const char *Name, tSpiderValue *Value); -extern void Variable_Destroy(tAST_Variable *Variable); - -// === CODE === -/** - * \brief Library Entry Point - */ -int SoMain() -{ - return 0; -} - -/** - * \brief Parse a script - */ -tSpiderScript *SpiderScript_ParseFile(tSpiderVariant *Variant, const char *Filename) -{ - char *data; - int fLen; - FILE *fp; - tSpiderScript *ret; - - fp = fopen(Filename, "r"); - if( !fp ) { - return NULL; - } - - fseek(fp, 0, SEEK_END); - fLen = ftell(fp); - fseek(fp, 0, SEEK_SET); - - // Allocate and read data - data = malloc(fLen + 1); - if(!data) return NULL; - fLen = fread(data, 1, fLen, fp); - fclose(fp); - if( fLen < 0 ) { - free(data); - return NULL; - } - data[fLen] = '\0'; - - - // Create the script - ret = malloc(sizeof(tSpiderScript)); - ret->Variant = Variant; - ret->Functions = NULL; - ret->LastFunction = NULL; - - ret->CurNamespace = NULL; - if( Parse_Buffer(ret, data, Filename) ) { - free(data); - free(ret); - return NULL; - } - - free(data); - - - // HACK!! - #if 1 - // - Save AST to a file - { - char cacheFilename[strlen(Filename)+6+1]; - strcpy(cacheFilename, Filename); - strcat(cacheFilename, ".ast"); - - SpiderScript_SaveAST(ret, cacheFilename); - } - #endif - // - Save Bytecode too - { - char cacheFilename[strlen(Filename)+6+1]; - strcpy(cacheFilename, Filename); - strcat(cacheFilename, ".bc"); - - SpiderScript_SaveBytecode(ret, cacheFilename); - } - - return ret; -} - -int SpiderScript_SaveAST(tSpiderScript *Script, const char *Filename) -{ - size_t size; - FILE *fp; - void *data; - printf("Total Size: "); - fflush(stdout); - size = AST_WriteScript(NULL, Script); - printf("0x%x bytes\n", (unsigned)size); - - fp = fopen(Filename, "wb"); - if(!fp) return 1; - - data = malloc(size); - if(!data) { - fclose(fp); - return -1; - } - - size = AST_WriteScript(data, Script); - fwrite(data, size, 1, fp); - free(data); - - fclose(fp); - return 0; -} - -/** - * \brief Free a script - */ -void SpiderScript_Free(tSpiderScript *Script) -{ - tScript_Function *fcn = Script->Functions; - tScript_Function *nextFcn; - - // Free functions - while(fcn) - { - if(fcn->ASTFcn) AST_FreeNode( fcn->ASTFcn ); - if(fcn->BCFcn) Bytecode_DeleteFunction( fcn->BCFcn ); - - nextFcn = fcn->Next; - free( fcn ); - fcn = nextFcn; - } - - free(Script); -} diff --git a/Usermode/Libraries/libspiderscript.so_src/parse.c b/Usermode/Libraries/libspiderscript.so_src/parse.c deleted file mode 100644 index e6d96942..00000000 --- a/Usermode/Libraries/libspiderscript.so_src/parse.c +++ /dev/null @@ -1,1082 +0,0 @@ -/* - * Acess2 - SpiderScript - * - Parser - */ -#include -#include -#include -#include -#include -#define WANT_TOKEN_STRINGS 1 -#include "tokens.h" -#include "ast.h" -#include "common.h" - -#define DEBUG 0 -#define SUPPORT_BREAK_TAGS 1 - -// === PROTOTYPES === - int Parse_Buffer(tSpiderScript *Script, const char *Buffer, const char *Filename); -void *Parse_FunctionDefinition(tSpiderScript *Script, tParser *Parser, int Type); -tAST_Node *Parse_DoCodeBlock(tParser *Parser); -tAST_Node *Parse_DoBlockLine(tParser *Parser); -tAST_Node *Parse_GetVarDef(tParser *Parser, int Type); - -tAST_Node *Parse_DoExpr0(tParser *Parser); // Assignment -tAST_Node *Parse_DoExpr1(tParser *Parser); // Boolean Operators -tAST_Node *Parse_DoExpr2(tParser *Parser); // Comparison Operators -tAST_Node *Parse_DoExpr3(tParser *Parser); // Bitwise Operators -tAST_Node *Parse_DoExpr4(tParser *Parser); // Bit Shifts -tAST_Node *Parse_DoExpr5(tParser *Parser); // Arithmatic -tAST_Node *Parse_DoExpr6(tParser *Parser); // Mult & Div -tAST_Node *Parse_DoExpr7(tParser *Parser); // Right Unary Operations -tAST_Node *Parse_DoExpr8(tParser *Parser); // Left Unary Operations - -tAST_Node *Parse_DoParen(tParser *Parser); // Parenthesis (Always Last) -tAST_Node *Parse_DoValue(tParser *Parser); // Values - -tAST_Node *Parse_GetString(tParser *Parser); -tAST_Node *Parse_GetNumeric(tParser *Parser); -tAST_Node *Parse_GetVariable(tParser *Parser); -tAST_Node *Parse_GetIdent(tParser *Parser, int bObjectCreate); - -void SyntaxAssert(tParser *Parser, int Have, int Want); -void SyntaxError(tParser *Parser, int bFatal, const char *Message, ...); - -#define SyntaxAssert(_parser, _have, _want) do { \ - int have = (_have), want = (_want); \ - if( (have) != (want) ) { \ - SyntaxError(Parser, 1, "Unexpected %s(%i), expecting %s(%i)\n", \ - csaTOKEN_NAMES[have], have, csaTOKEN_NAMES[want], want); \ - return NULL; \ - } \ -}while(0) - -#define TODO(Parser, message...) do {\ - fprintf(stderr, "TODO: "message);\ - longjmp(Parser->JmpTarget, -1);\ -}while(0) - -// === CODE === -/** - * \brief Parse a buffer into a syntax tree - */ -int Parse_Buffer(tSpiderScript *Script, const char *Buffer, const char *Filename) -{ - tParser parser = {0}; - tParser *Parser = &parser; //< Keeps code consistent - tAST_Node *mainCode, *node; - int type; - tScript_Function *fcn; - - #if DEBUG >= 2 - printf("Parse_Buffer: (Variant=%p, Buffer=%p)\n", Variant, Buffer); - #endif - - // Initialise parser - parser.LastToken = -1; - parser.NextToken = -1; - parser.CurLine = 1; - parser.BufStart = Buffer; - parser.CurPos = Buffer; - // hackery to do reference counting - parser.Filename = malloc(sizeof(int)+strlen(Filename)+1); - strcpy(parser.Filename + sizeof(int), Filename); - *(int*)(parser.Filename) = 0; // Set reference count - parser.Filename += sizeof(int); // Move filename - parser.ErrorHit = 0; - - mainCode = AST_NewCodeBlock(&parser); - - // Give us an error fallback - if( setjmp( parser.JmpTarget ) != 0 ) - { - AST_FreeNode( mainCode ); - - for(fcn = Script->Functions; fcn; ) - { - tScript_Function *nextFcn; - - AST_FreeNode( fcn->ASTFcn ); - - nextFcn = fcn->Next; - free( fcn ); - fcn = nextFcn; - } - return -1; - } - - // Parse the file! - while(Parser->Token != TOK_EOF) - { - switch( GetToken(Parser) ) - { - case TOK_EOF: - break; - - // Typed variables/functions - case TOKEN_GROUP_TYPES: - TOKEN_GET_DATATYPE(type, Parser->Token); - - switch(GetToken(Parser)) - { - // Define a function (pass on to the other function definition code) - case TOK_IDENT: - PutBack(Parser); - if( Parse_FunctionDefinition(Script, Parser, type) == NULL ) - longjmp(Parser->JmpTarget, -1); - break ; - // Define a variable - case TOK_VARIABLE: - node = Parse_GetVarDef(Parser, type); - if(!node) longjmp(Parser->JmpTarget, -1); - - AST_AppendNode( mainCode, node ); - // Can't use SyntaxAssert because that returns - if(GetToken(Parser) != TOK_SEMICOLON) { - SyntaxError(Parser, 1, "Unexpected %s, expected TOK_SEMICOLON", - csaTOKEN_NAMES[Parser->Token]); - longjmp(Parser->JmpTarget, -1); - } - break; - default: - SyntaxError(Parser, 1, "Unexpected %s, expected TOK_IDENT or TOK_VARIABLE\n", - csaTOKEN_NAMES[Parser->Token]); - break; - } - break; - - // Define a function - case TOK_RWD_FUNCTION: - if( !Script->Variant->bDyamicTyped ) { - SyntaxError(Parser, 1, "Dynamic functions are invalid in static mode"); - longjmp(Parser->JmpTarget, -1); - } - - type = SS_DATATYPE_DYNAMIC; - - if( Parse_FunctionDefinition(Script, Parser, SS_DATATYPE_DYNAMIC) == NULL ) - longjmp(Parser->JmpTarget, -1); - - break; - - // Ordinary Statement - default: - PutBack(Parser); - node = Parse_DoBlockLine(Parser); - if(!node) longjmp(Parser->JmpTarget, -1); - AST_AppendNode( mainCode, node ); - break; - } - - // Jump to error handler on error - if(Parser->ErrorHit) - longjmp(Parser->JmpTarget, -1); - } - - AST_AppendFunction( Script, "", SS_DATATYPE_INTEGER, NULL, mainCode ); - - //printf("---- %p parsed as SpiderScript ----\n", Buffer); - - return 0; -} - -void *Parse_FunctionDefinition(tSpiderScript *Script, tParser *Parser, int Type) -{ - char *name; - int rv; - tAST_Node *first_arg, *last_arg, *code; - - last_arg = (void*)&first_arg; // HACK - - SyntaxAssert(Parser, GetToken(Parser), TOK_IDENT ); - - name = strndup( Parser->TokenStr, Parser->TokenLen ); - #if DEBUG - printf("DefFCN %s\n", name); - #endif - - // Get arguments - SyntaxAssert(Parser, GetToken(Parser), TOK_PAREN_OPEN ); - if( LookAhead(Parser) != TOK_PAREN_CLOSE ) - { - do { - int type = SS_DATATYPE_DYNAMIC; - GetToken(Parser); - // Non dynamic typed variants must use data types - if( !Script->Variant->bDyamicTyped ) { - TOKEN_GET_DATATYPE(type, Parser->Token); - GetToken(Parser); - } - last_arg->NextSibling = Parse_GetVarDef(Parser, type); - last_arg = last_arg->NextSibling; - last_arg->NextSibling = NULL; - } while(GetToken(Parser) == TOK_COMMA); - } - else - GetToken(Parser); - SyntaxAssert(Parser, Parser->Token, TOK_PAREN_CLOSE ); - - code = Parse_DoCodeBlock(Parser); - - rv = AST_AppendFunction( Script, name, Type, first_arg, code ); - - // Clean up argument definition nodes - { - tAST_Node *nextarg; - for( ; first_arg; first_arg = nextarg ) - { - nextarg = first_arg->NextSibling; - AST_FreeNode(first_arg); - } - } - - free(name); - - return rv == 0 ? (void*)1 : NULL; -} - -/** - * \brief Parse a block of code surrounded by { } - */ -tAST_Node *Parse_DoCodeBlock(tParser *Parser) -{ - tAST_Node *ret; - - // Check if we are being called for a one-liner - if( GetToken(Parser) != TOK_BRACE_OPEN ) { - PutBack(Parser); - return Parse_DoBlockLine(Parser); - } - - ret = AST_NewCodeBlock(Parser); - - while( LookAhead(Parser) != TOK_BRACE_CLOSE ) - { - tAST_Node *node = Parse_DoBlockLine(Parser); - if(!node) { - AST_FreeNode(ret); - return NULL; - } - AST_AppendNode( ret, node ); - } - GetToken(Parser); // Omnomnom - return ret; -} - -/** - * \brief Parse a line in a block - */ -tAST_Node *Parse_DoBlockLine(tParser *Parser) -{ - tAST_Node *ret; - - //printf("Parse_DoBlockLine: Line %i\n", Parser->CurLine); - - switch(LookAhead(Parser)) - { - // New block - case TOK_BRACE_OPEN: - return Parse_DoCodeBlock(Parser); - - // Empty statement - case TOK_SEMICOLON: - GetToken(Parser); - return NULL; - - // Return from a method - case TOK_RWD_RETURN: - GetToken(Parser); - ret = AST_NewUniOp(Parser, NODETYPE_RETURN, Parse_DoExpr0(Parser)); - break; - - // Break / Continue (end a loop / go to next iteration) - case TOK_RWD_CONTINUE: - case TOK_RWD_BREAK: - { - int tok; - char *ident = NULL; - tok = GetToken(Parser); - // Get the number of nesting levels to break - if(LookAhead(Parser) == TOK_IDENT) - { - GetToken(Parser); - ident = strndup(Parser->TokenStr, Parser->TokenLen); - } - // Get the action - switch(tok) - { - case TOK_RWD_BREAK: ret = AST_NewBreakout(Parser, NODETYPE_BREAK, ident); break; - case TOK_RWD_CONTINUE: ret = AST_NewBreakout(Parser, NODETYPE_CONTINUE, ident); break; - default: - SyntaxError(Parser, 1, "BUG Unhandled break/continue (%s)", - csaTOKEN_NAMES[tok]); - return NULL; - } - if(ident) free(ident); - } - break; - - // Control Statements - case TOK_RWD_IF: - { - tAST_Node *cond, *true, *false = NULL; - GetToken(Parser); // eat the if - - SyntaxAssert(Parser, GetToken(Parser), TOK_PAREN_OPEN); - cond = Parse_DoExpr0(Parser); // Get condition - SyntaxAssert(Parser, GetToken(Parser), TOK_PAREN_CLOSE); - true = Parse_DoCodeBlock(Parser); - if( LookAhead(Parser) == TOK_RWD_ELSE ) { - GetToken(Parser); - false = Parse_DoCodeBlock(Parser); - } - else - false = AST_NewNop(Parser); - ret = AST_NewIf(Parser, cond, true, false); - } - return ret; - - case TOK_RWD_FOR: - { - char *tag = NULL; - tAST_Node *init=NULL, *cond=NULL, *inc=NULL, *code; - GetToken(Parser); // Eat 'for' - - #if SUPPORT_BREAK_TAGS - if(LookAhead(Parser) == TOK_LT) - { - GetToken(Parser); - SyntaxAssert(Parser, GetToken(Parser), TOK_IDENT); - tag = strndup(Parser->TokenStr, Parser->TokenLen); - SyntaxAssert(Parser, GetToken(Parser), TOK_GT); - } - #endif - - SyntaxAssert(Parser, GetToken(Parser), TOK_PAREN_OPEN); - - if(LookAhead(Parser) != TOK_SEMICOLON) - init = Parse_DoExpr0(Parser); - - SyntaxAssert(Parser, GetToken(Parser), TOK_SEMICOLON); - - if(LookAhead(Parser) != TOK_SEMICOLON) - cond = Parse_DoExpr0(Parser); - - SyntaxAssert(Parser, GetToken(Parser), TOK_SEMICOLON); - - if(LookAhead(Parser) != TOK_PAREN_CLOSE) - inc = Parse_DoExpr0(Parser); - - SyntaxAssert(Parser, GetToken(Parser), TOK_PAREN_CLOSE); - - code = Parse_DoCodeBlock(Parser); - ret = AST_NewLoop(Parser, tag, init, 0, cond, inc, code); - if(tag) free(tag); - } - return ret; - - case TOK_RWD_DO: - { - const char *tag = ""; - tAST_Node *code, *cond; - GetToken(Parser); // Eat 'do' - - #if SUPPORT_BREAK_TAGS - if(LookAhead(Parser) == TOK_LT) - { - GetToken(Parser); - SyntaxAssert(Parser, GetToken(Parser), TOK_IDENT); - tag = strndup(Parser->TokenStr, Parser->TokenLen); - SyntaxAssert(Parser, GetToken(Parser), TOK_GT); - } - #endif - - code = Parse_DoCodeBlock(Parser); - SyntaxAssert( Parser, GetToken(Parser), TOK_RWD_WHILE ); - SyntaxAssert( Parser, GetToken(Parser), TOK_PAREN_OPEN ); - cond = Parse_DoExpr0(Parser); - SyntaxAssert( Parser, GetToken(Parser), TOK_PAREN_CLOSE ); - ret = AST_NewLoop(Parser, tag, AST_NewNop(Parser), 1, cond, AST_NewNop(Parser), code); - } - break; - case TOK_RWD_WHILE: - { - const char *tag = ""; - tAST_Node *code, *cond; - GetToken(Parser); // Eat 'while' - - #if SUPPORT_BREAK_TAGS - if(LookAhead(Parser) == TOK_LT) - { - GetToken(Parser); - SyntaxAssert(Parser, GetToken(Parser), TOK_IDENT); - tag = strndup(Parser->TokenStr, Parser->TokenLen); - SyntaxAssert(Parser, GetToken(Parser), TOK_GT); - } - #endif - - SyntaxAssert( Parser, GetToken(Parser), TOK_PAREN_OPEN ); - cond = Parse_DoExpr0(Parser); - SyntaxAssert( Parser, GetToken(Parser), TOK_PAREN_CLOSE ); - code = Parse_DoCodeBlock(Parser); - ret = AST_NewLoop(Parser, tag, AST_NewNop(Parser), 0, cond, AST_NewNop(Parser), code); - } - return ret; - - // Define Variables - case TOKEN_GROUP_TYPES: - { - int type; - GetToken(Parser); - TOKEN_GET_DATATYPE(type, Parser->Token); - - SyntaxAssert(Parser, GetToken(Parser), TOK_VARIABLE); - - ret = Parse_GetVarDef(Parser, type); - } - break; - - // Default - default: - //printf("exp0\n"); - ret = Parse_DoExpr0(Parser); - break; - } - - SyntaxAssert(Parser, GetToken(Parser), TOK_SEMICOLON ); - return ret; -} - -/** - * \brief Get a variable definition - */ -tAST_Node *Parse_GetVarDef(tParser *Parser, int Type) -{ - char name[Parser->TokenLen]; - tAST_Node *ret; - - SyntaxAssert(Parser, Parser->Token, TOK_VARIABLE); - - // copy the name (trimming the $) - memcpy(name, Parser->TokenStr+1, Parser->TokenLen-1); - name[Parser->TokenLen-1] = 0; - // Define the variable - ret = AST_NewDefineVar(Parser, Type, name); - // Handle arrays - while( LookAhead(Parser) == TOK_SQUARE_OPEN ) - { - tAST_Node *node; - GetToken(Parser); - node = Parse_DoExpr0(Parser); - if(!node) { - AST_FreeNode(ret); - return NULL; - } - AST_AppendNode(ret, node); - SyntaxAssert(Parser, GetToken(Parser), TOK_SQUARE_CLOSE); - } - - if( LookAhead(Parser) == TOK_ASSIGN ) - { - GetToken(Parser); - ret->DefVar.InitialValue = Parse_DoExpr0(Parser); - if(!ret->DefVar.InitialValue) { - AST_FreeNode(ret); - return NULL; - } - } - - return ret; -} - -/** - * \brief Assignment Operations - */ -tAST_Node *Parse_DoExpr0(tParser *Parser) -{ - #define _next Parse_DoExpr1 - tAST_Node *ret = _next(Parser); - int cont = 1; - - while( cont ) - { - // Check Assignment - switch(GetToken(Parser)) - { - case TOK_ASSIGN: - ret = AST_NewAssign(Parser, NODETYPE_NOP, ret, _next(Parser)); - break; - case TOK_ASSIGN_DIV: - ret = AST_NewAssign(Parser, NODETYPE_DIVIDE, ret, _next(Parser)); - break; - case TOK_ASSIGN_MUL: - ret = AST_NewAssign(Parser, NODETYPE_MULTIPLY, ret, _next(Parser)); - break; - case TOK_ASSIGN_PLUS: - ret = AST_NewAssign(Parser, NODETYPE_ADD, ret, _next(Parser)); - break; - case TOK_ASSIGN_MINUS: - ret = AST_NewAssign(Parser, NODETYPE_SUBTRACT, ret, _next(Parser)); - break; - default: - #if DEBUG >= 2 - printf("Parse_DoExpr0: Parser->Token = %i\n", Parser->Token); - #endif - PutBack(Parser); - cont = 0; - break; - } - } - return ret; - #undef _next -} - -/** - * \brief Logical/Boolean Operators - */ -tAST_Node *Parse_DoExpr1(tParser *Parser) -{ - #define _next Parse_DoExpr2 - tAST_Node *ret = _next(Parser); - int cont = 1; - - while( cont ) - { - switch(GetToken(Parser)) - { - case TOK_LOGICAND: - ret = AST_NewBinOp(Parser, NODETYPE_LOGICALAND, ret, _next(Parser)); - break; - case TOK_LOGICOR: - ret = AST_NewBinOp(Parser, NODETYPE_LOGICALOR, ret, _next(Parser)); - break; - case TOK_LOGICXOR: - ret = AST_NewBinOp(Parser, NODETYPE_LOGICALXOR, ret, _next(Parser)); - break; - default: - PutBack(Parser); - cont = 0; - break; - } - } - return ret; - #undef _next -} - -// -------------------- -// Expression 2 - Comparison Operators -// -------------------- -tAST_Node *Parse_DoExpr2(tParser *Parser) -{ - #define _next Parse_DoExpr3 - tAST_Node *ret = _next(Parser); - int cont = 1; - - while( cont ) - { - // Check token - switch(GetToken(Parser)) - { - case TOK_EQUALS: - ret = AST_NewBinOp(Parser, NODETYPE_EQUALS, ret, _next(Parser)); - break; - case TOK_LT: - ret = AST_NewBinOp(Parser, NODETYPE_LESSTHAN, ret, _next(Parser)); - break; - case TOK_GT: - ret = AST_NewBinOp(Parser, NODETYPE_GREATERTHAN, ret, _next(Parser)); - break; - case TOK_LTE: - ret = AST_NewBinOp(Parser, NODETYPE_LESSTHANEQUAL, ret, _next(Parser)); - break; - case TOK_GTE: - ret = AST_NewBinOp(Parser, NODETYPE_GREATERTHANEQUAL, ret, _next(Parser)); - break; - default: - PutBack(Parser); - cont = 0; - break; - } - } - return ret; - #undef _next -} - -/** - * \brief Bitwise Operations - */ -tAST_Node *Parse_DoExpr3(tParser *Parser) -{ - #define _next Parse_DoExpr4 - tAST_Node *ret = _next(Parser); - int cont = 1; - - while( cont ) - { - // Check Token - switch(GetToken(Parser)) - { - case TOK_OR: - ret = AST_NewBinOp(Parser, NODETYPE_BWOR, ret, _next(Parser)); - break; - case TOK_AND: - ret = AST_NewBinOp(Parser, NODETYPE_BWAND, ret, _next(Parser)); - break; - case TOK_XOR: - ret = AST_NewBinOp(Parser, NODETYPE_BWXOR, ret, _next(Parser)); - break; - default: - PutBack(Parser); - cont = 0; - break; - } - } - return ret; - #undef _next -} - -// -------------------- -// Expression 4 - Shifts -// -------------------- -tAST_Node *Parse_DoExpr4(tParser *Parser) -{ - #define _next Parse_DoExpr5 - tAST_Node *ret = _next(Parser); - int cont = 1; - - while( cont ) - { - switch(GetToken(Parser)) - { - case TOK_SHL: - ret = AST_NewBinOp(Parser, NODETYPE_BITSHIFTLEFT, ret, _next(Parser)); - break; - case TOK_SHR: - ret = AST_NewBinOp(Parser, NODETYPE_BITSHIFTRIGHT, ret, _next(Parser)); - break; - default: - PutBack(Parser); - cont = 0; - break; - } - } - - return ret; - #undef _next -} - -// -------------------- -// Expression 5 - Arithmatic -// -------------------- -tAST_Node *Parse_DoExpr5(tParser *Parser) -{ - #define _next Parse_DoExpr6 - tAST_Node *ret = _next(Parser); - int cont = 1; - - // While loop is added to ensure that the evaluation order ends up as - // right to left. - // E.g. a + b + c + d ends up as (((a + b) + c) + d) for casting - while( cont ) - { - switch(GetToken(Parser)) - { - case TOK_PLUS: - ret = AST_NewBinOp(Parser, NODETYPE_ADD, ret, _next(Parser)); - break; - case TOK_MINUS: - ret = AST_NewBinOp(Parser, NODETYPE_SUBTRACT, ret, _next(Parser)); - break; - default: - PutBack(Parser); - cont = 0; - break; - } - } - - return ret; - #undef _next -} - -// -------------------- -// Expression 6 - Multiplcation & Division -// -------------------- -tAST_Node *Parse_DoExpr6(tParser *Parser) -{ - #define _next Parse_DoExpr7 - tAST_Node *ret = _next(Parser); - int cont = 1; - - while( cont ) - { - switch(GetToken(Parser)) - { - case TOK_MUL: - ret = AST_NewBinOp(Parser, NODETYPE_MULTIPLY, ret, _next(Parser)); - break; - case TOK_DIV: - ret = AST_NewBinOp(Parser, NODETYPE_DIVIDE, ret, _next(Parser)); - break; - default: - PutBack(Parser); - cont = 0; - break; - } - } - - return ret; - #undef _next -} - -// -------------------- -// Expression 7 - Right Unary Operations -// -------------------- -tAST_Node *Parse_DoExpr7(tParser *Parser) -{ - tAST_Node *ret = Parse_DoExpr8(Parser); - - switch(GetToken(Parser)) - { - case TOK_INCREMENT: - ret = AST_NewUniOp(Parser, NODETYPE_POSTINC, ret); - break; - case TOK_DECREMENT: - ret = AST_NewUniOp(Parser, NODETYPE_POSTDEC, ret); - break; - default: - PutBack(Parser); - break; - } - return ret; -} - -// -------------------- -// Expression 8 - Left Unary Operations -// -------------------- -tAST_Node *Parse_DoExpr8(tParser *Parser) -{ - switch(GetToken(Parser)) - { - case TOK_INCREMENT: - return AST_NewAssign(Parser, NODETYPE_ADD, Parse_DoExpr8(Parser), AST_NewInteger(Parser, 1)); - case TOK_DECREMENT: - return AST_NewAssign(Parser, NODETYPE_SUBTRACT, Parse_DoExpr8(Parser), AST_NewInteger(Parser, 1)); - case TOK_MINUS: - return AST_NewUniOp(Parser, NODETYPE_NEGATE, Parse_DoExpr8(Parser)); - case TOK_LOGICNOT: - return AST_NewUniOp(Parser, NODETYPE_LOGICALNOT, Parse_DoExpr8(Parser)); - case TOK_BWNOT: - return AST_NewUniOp(Parser, NODETYPE_BWNOT, Parse_DoExpr8(Parser)); - default: - PutBack(Parser); - return Parse_DoParen(Parser); - } -} - -// -------------------- -// 2nd Last Expression - Parens -// -------------------- -tAST_Node *Parse_DoParen(tParser *Parser) -{ - #if DEBUG >= 2 - printf("Parse_DoParen: (Parser=%p)\n", Parser); - #endif - if(LookAhead(Parser) == TOK_PAREN_OPEN) - { - tAST_Node *ret; - int type; - GetToken(Parser); - - // TODO: Handle casts here - switch(LookAhead(Parser)) - { - case TOKEN_GROUP_TYPES: - GetToken(Parser); - TOKEN_GET_DATATYPE(type, Parser->Token); - SyntaxAssert(Parser, GetToken(Parser), TOK_PAREN_CLOSE); - ret = AST_NewCast(Parser, type, Parse_DoParen(Parser)); - break; - default: - ret = Parse_DoExpr0(Parser); - SyntaxAssert(Parser, GetToken(Parser), TOK_PAREN_CLOSE); - break; - } - return ret; - } - else - return Parse_DoValue(Parser); -} - -// -------------------- -// Last Expression - Value -// -------------------- -tAST_Node *Parse_DoValue(tParser *Parser) -{ - int tok = LookAhead(Parser); - - #if DEBUG >= 2 - printf("Parse_DoValue: tok = %i\n", tok); - #endif - - switch(tok) - { - case TOK_STR: - return Parse_GetString(Parser); - case TOK_INTEGER: - return Parse_GetNumeric(Parser); - - case TOK_REAL: - GetToken(Parser); - return AST_NewReal( Parser, atof(Parser->TokenStr) ); - - case TOK_IDENT: - return Parse_GetIdent(Parser, 0); - case TOK_VARIABLE: - return Parse_GetVariable(Parser); - case TOK_RWD_NULL: - GetToken(Parser); - return AST_NewNop(Parser); // NODETYPE_NOP returns NULL - case TOK_RWD_NEW: - GetToken(Parser); - return Parse_GetIdent(Parser, 1); - - default: - fprintf(stderr, "Syntax Error: Unexpected %s on line %i, Expected TOK_T_VALUE\n", - csaTOKEN_NAMES[tok], Parser->CurLine); - longjmp( Parser->JmpTarget, -1 ); - } -} - -/** - * \brief Get a string - */ -tAST_Node *Parse_GetString(tParser *Parser) -{ - tAST_Node *ret; - int i, j; - GetToken( Parser ); - - { - char data[ Parser->TokenLen - 2 ]; - j = 0; - - for( i = 1; i < Parser->TokenLen - 1; i++ ) - { - if( Parser->TokenStr[i] == '\\' ) { - i ++; - switch( Parser->TokenStr[i] ) - { - case 'n': data[j++] = '\n'; break; - case 'r': data[j++] = '\r'; break; - default: - // TODO: Octal Codes - // TODO: Error/Warning? - break; - } - } - else { - data[j++] = Parser->TokenStr[i]; - } - } - - // TODO: Parse Escape Codes - ret = AST_NewString( Parser, data, j ); - } - return ret; -} - -/** - * \brief Get a numeric value - */ -tAST_Node *Parse_GetNumeric(tParser *Parser) -{ - uint64_t value = 0; - const char *pos; - SyntaxAssert( Parser, GetToken( Parser ), TOK_INTEGER ); - pos = Parser->TokenStr; - //printf("pos = %p, *pos = %c\n", pos, *pos); - - if( *pos == '0' ) - { - pos ++; - if(*pos == 'x') { - pos ++; - for( ;; pos++) - { - value *= 16; - if( '0' <= *pos && *pos <= '9' ) { - value += *pos - '0'; - continue; - } - if( 'A' <= *pos && *pos <= 'F' ) { - value += *pos - 'A' + 10; - continue; - } - if( 'a' <= *pos && *pos <= 'f' ) { - value += *pos - 'a' + 10; - continue; - } - break; - } - } - else { - while( '0' <= *pos && *pos <= '7' ) { - value = value*8 + *pos - '0'; - pos ++; - } - } - } - else { - while( '0' <= *pos && *pos <= '9' ) { - value = value*10 + *pos - '0'; - pos ++; - } - } - - return AST_NewInteger( Parser, value ); -} - -/** - * \brief Get a variable - */ -tAST_Node *Parse_GetVariable(tParser *Parser) -{ - tAST_Node *ret; - SyntaxAssert( Parser, GetToken(Parser), TOK_VARIABLE ); - { - char name[Parser->TokenLen]; - memcpy(name, Parser->TokenStr+1, Parser->TokenLen-1); - name[Parser->TokenLen-1] = 0; - ret = AST_NewVariable( Parser, name ); - #if DEBUG >= 2 - printf("Parse_GetVariable: name = '%s'\n", name); - #endif - } - for(;;) - { - GetToken(Parser); - if( Parser->Token == TOK_SQUARE_OPEN ) - { - ret = AST_NewBinOp(Parser, NODETYPE_INDEX, ret, Parse_DoExpr0(Parser)); - SyntaxAssert(Parser, GetToken(Parser), TOK_SQUARE_CLOSE); - continue ; - } - if( Parser->Token == TOK_ELEMENT ) - { - SyntaxAssert(Parser, GetToken(Parser), TOK_IDENT); - // Method Call - if( LookAhead(Parser) == TOK_PAREN_OPEN ) - { - char name[Parser->TokenLen+1]; - memcpy(name, Parser->TokenStr, Parser->TokenLen); - name[Parser->TokenLen] = 0; - ret = AST_NewMethodCall(Parser, ret, name); - GetToken(Parser); // Eat the '(' - // Read arguments - if( GetToken(Parser) != TOK_PAREN_CLOSE ) - { - PutBack(Parser); - do { - AST_AppendFunctionCallArg( ret, Parse_DoExpr0(Parser) ); - } while(GetToken(Parser) == TOK_COMMA); - SyntaxAssert( Parser, Parser->Token, TOK_PAREN_CLOSE ); - } - - } - // Attribute - else - { - char name[Parser->TokenLen]; - memcpy(name, Parser->TokenStr+1, Parser->TokenLen-1); - name[Parser->TokenLen-1] = 0; - ret = AST_NewClassElement(Parser, ret, name); - } - continue ; - } - - break ; - } - PutBack(Parser); - return ret; -} - -/** - * \brief Get an identifier (constant or function call) - */ -tAST_Node *Parse_GetIdent(tParser *Parser, int bObjectCreate) -{ - tAST_Node *ret = NULL; - char *name; - SyntaxAssert(Parser, GetToken(Parser), TOK_IDENT ); - name = strndup( Parser->TokenStr, Parser->TokenLen ); - - #if USE_SCOPE_CHAR - if( GetToken(Parser) == TOK_SCOPE ) - { - ret = AST_NewScopeDereference( Parser, name, Parse_GetIdent(Parser, bObjectCreate) ); - free(name); - return ret; - } - PutBack(Parser); - #endif - - if( GetToken(Parser) == TOK_PAREN_OPEN ) - { - #if DEBUG >= 2 - printf("Parse_GetIdent: Calling '%s'\n", name); - #endif - // Function Call - if( bObjectCreate ) - ret = AST_NewCreateObject( Parser, name ); - else - ret = AST_NewFunctionCall( Parser, name ); - // Read arguments - if( GetToken(Parser) != TOK_PAREN_CLOSE ) - { - PutBack(Parser); - do { - #if DEBUG >= 2 - printf(" Parse_GetIdent: Argument\n"); - #endif - AST_AppendFunctionCallArg( ret, Parse_DoExpr0(Parser) ); - } while(GetToken(Parser) == TOK_COMMA); - SyntaxAssert( Parser, Parser->Token, TOK_PAREN_CLOSE ); - #if DEBUG >= 2 - printf(" Parse_GetIdent: All arguments parsed\n"); - #endif - } - } - else - { - // Runtime Constant / Variable (When implemented) - #if DEBUG >= 2 - printf("Parse_GetIdent: Referencing '%s'\n", name); - #endif - PutBack(Parser); - if( bObjectCreate ) // Void constructor (TODO: Should this be an error?) - ret = AST_NewCreateObject( Parser, name ); - else - ret = AST_NewConstant( Parser, name ); - } - - free(name); - return ret; -} - - -void SyntaxError(tParser *Parser, int bFatal, const char *Message, ...) -{ - va_list args; - va_start(args, Message); - fprintf(stderr, "%s:%i: error: ", Parser->Filename, Parser->CurLine); - vfprintf(stderr, Message, args); - fprintf(stderr, "\n"); - va_end(args); - - if( bFatal ) { - //longjmp(Parser->JmpTarget, -1); - Parser->ErrorHit = 1; - } -} - diff --git a/Usermode/Libraries/libspiderscript.so_src/tokens.h b/Usermode/Libraries/libspiderscript.so_src/tokens.h deleted file mode 100644 index 44176b0b..00000000 --- a/Usermode/Libraries/libspiderscript.so_src/tokens.h +++ /dev/null @@ -1,200 +0,0 @@ -/* - */ -#ifndef _TOKENS_H_ -#define _TOKENS_H_ - -#include - -// Make the scope character ('.') be a symbol, otherwise it's just -// a ident character -#define USE_SCOPE_CHAR 1 - -// === TYPES === -typedef struct -{ - // Lexer State - const char *BufStart; - const char *CurPos; - - char *Filename; - - int LastLine; - int LastToken, LastTokenLen; - const char *LastTokenStr; - - int NextLine; - int NextToken, NextTokenLen; - const char *NextTokenStr; - - int CurLine; - int Token, TokenLen; - const char *TokenStr; - - jmp_buf JmpTarget; - int ErrorHit; -} tParser; - -// === FUNCTIONS === - int GetToken(tParser *File); -void PutBack(tParser *File); - int LookAhead(tParser *File); - -// === CONSTANTS === -enum eTokens -{ - TOK_INVAL, - TOK_EOF, - - // Primitives - TOK_STR, - TOK_INTEGER, - TOK_REAL, - TOK_VARIABLE, - TOK_IDENT, - - // Reserved Words - // - Definitions - TOK_RWD_FUNCTION, - TOK_RWD_NAMESPACE, - // - Control Flow - TOK_RWD_NEW, - TOK_RWD_RETURN, - TOK_RWD_BREAK, - TOK_RWD_CONTINUE, - // - Blocks - TOK_RWD_IF, - TOK_RWD_ELSE, - TOK_RWD_DO, - TOK_RWD_WHILE, - TOK_RWD_FOR, - // - Value - TOK_RWD_NULL, - // - Types - TOK_RWD_VOID, - TOK_RWD_OBJECT, - TOK_RWD_OPAQUE, - TOK_RWD_STRING, - TOK_RWD_INTEGER, - TOK_RWD_REAL, - - // - TOK_ASSIGN, - TOK_SEMICOLON, - TOK_COMMA, - TOK_SCOPE, - TOK_ELEMENT, - - // Comparisons - TOK_EQUALS, - TOK_LT, TOK_LTE, - TOK_GT, TOK_GTE, - - // Operations - TOK_BWNOT, TOK_LOGICNOT, - TOK_DIV, TOK_MUL, - TOK_PLUS, TOK_MINUS, - TOK_SHL, TOK_SHR, - TOK_LOGICAND, TOK_LOGICOR, TOK_LOGICXOR, - TOK_AND, TOK_OR, TOK_XOR, - - // Assignment Operations - TOK_INCREMENT, TOK_DECREMENT, - TOK_ASSIGN_DIV, TOK_ASSIGN_MUL, - TOK_ASSIGN_PLUS, TOK_ASSIGN_MINUS, - TOK_ASSIGN_SHL, TOK_ASSIGN_SHR, - TOK_ASSIGN_LOGICAND, TOK_ASSIGN_LOGICOR, TOK_ASSIGN_LOGXICOR, - TOK_ASSIGN_AND, TOK_ASSIGN_OR, TOK_ASSIGN_XOR, - - TOK_PAREN_OPEN, TOK_PAREN_CLOSE, - TOK_BRACE_OPEN, TOK_BRACE_CLOSE, - TOK_SQUARE_OPEN, TOK_SQUARE_CLOSE, - - TOK_LAST -}; - -#define TOKEN_GROUP_TYPES TOK_RWD_VOID:\ - case TOK_RWD_OBJECT:\ - case TOK_RWD_OPAQUE:\ - case TOK_RWD_INTEGER:\ - case TOK_RWD_STRING:\ - case TOK_RWD_REAL -#define TOKEN_GROUP_TYPES_STR "TOK_RWD_VOID, TOK_RWD_OBJECT, TOK_RWD_OPAQUE, TOK_RWD_INTEGER, TOK_RWD_STRING or TOK_RWD_REAL" - -#define TOKEN_GET_DATATYPE(_type, _tok) do { switch(_tok) {\ - case TOK_RWD_VOID: _type = SS_DATATYPE_UNDEF; break;\ - case TOK_RWD_INTEGER:_type = SS_DATATYPE_INTEGER; break;\ - case TOK_RWD_OPAQUE: _type = SS_DATATYPE_OPAQUE; break;\ - case TOK_RWD_OBJECT: _type = SS_DATATYPE_OBJECT; break;\ - case TOK_RWD_REAL: _type = SS_DATATYPE_REAL; break;\ - case TOK_RWD_STRING: _type = SS_DATATYPE_STRING; break;\ - default:_type=SS_DATATYPE_UNDEF;fprintf(stderr,\ - "ERROR: Unexpected %s, expected "TOKEN_GROUP_TYPES_STR"\n",csaTOKEN_NAMES[Parser->Token]);\ - break;\ - } } while(0) - -# if WANT_TOKEN_STRINGS -const char * const csaTOKEN_NAMES[] = { - "TOK_INVAL", - "TOK_EOF", - - "TOK_STR", - "TOK_INTEGER", - "TOK_REAL", - "TOK_VARIABLE", - "TOK_IDENT", - - "TOK_RWD_FUNCTION", - "TOK_RWD_NAMESPACE", - - "TOK_RWD_NEW", - "TOK_RWD_RETURN", - "TOK_RWD_BREAK", - "TOK_RWD_CONTINUE", - - "TOK_RWD_IF", - "TOK_RWD_ELSE", - "TOK_RWD_DO", - "TOK_RWD_WHILE", - "TOK_RWD_FOR", - - "TOK_RWD_NULL", - "TOK_RWD_VOID", - "TOK_RWD_OBJECT", - "TOK_RWD_OPAUQE", - "TOK_RWD_STRING", - "TOK_RWD_INTEGER", - "TOK_RWD_REAL", - - "TOK_ASSIGN", - "TOK_SEMICOLON", - "TOK_COMMA", - "TOK_SCOPE", - "TOK_ELEMENT", - - "TOK_EQUALS", - "TOK_LT", "TOK_LTE", - "TOK_GT", "TOK_GTE", - - "TOK_BWNOT", "TOK_LOGICNOT", - "TOK_DIV", "TOK_MUL", - "TOK_PLUS", "TOK_MINUS", - "TOK_SHL", "TOK_SHR", - "TOK_LOGICAND", "TOK_LOGICOR", "TOK_LOGICXOR", - "TOK_AND", "TOK_OR", "TOK_XOR", - - "TOK_INCREMENT", "TOK_DECREMENT", - "TOK_ASSIGN_DIV", "TOK_ASSIGN_MUL", - "TOK_ASSIGN_PLUS", "TOK_ASSIGN_MINUS", - "TOK_ASSIGN_SHL", "TOK_ASSIGN_SHR", - "TOK_ASSIGN_LOGICAND", "TOK_ASSIGN_LOGICOR", "TOK_ASSIGN_LOGICXOR", - "TOK_ASSIGN_AND", "TOK_ASSIGN_OR", "TOK_ASSIGN_XOR", - - "TOK_PAREN_OPEN", "TOK_PAREN_CLOSE", - "TOK_BRACE_OPEN", "TOK_BRACE_CLOSE", - "TOK_SQUARE_OPEN", "TOK_SQUARE_CLOSE", - - "TOK_LAST" -}; -# endif - -#endif diff --git a/Usermode/Libraries/libspiderscript.so_src/values.c b/Usermode/Libraries/libspiderscript.so_src/values.c deleted file mode 100644 index f72e2903..00000000 --- a/Usermode/Libraries/libspiderscript.so_src/values.c +++ /dev/null @@ -1,461 +0,0 @@ -/* - * SpiderScript Library - * by John Hodge (thePowersGang) - * - * values.c - * - Manage tSpiderValue objects - */ -#include -#include -#include -#include "spiderscript.h" - -// === IMPORTS === -extern void AST_RuntimeError(void *Node, const char *Format, ...); - -// === PROTOTYPES === -void SpiderScript_DereferenceValue(tSpiderValue *Object); -void SpiderScript_ReferenceValue(tSpiderValue *Object); -tSpiderValue *SpiderScript_CreateInteger(uint64_t Value); -tSpiderValue *SpiderScript_CreateReal(double Value); -tSpiderValue *SpiderScript_CreateString(int Length, const char *Data); -tSpiderValue *SpiderScript_CastValueTo(int Type, tSpiderValue *Source); - int SpiderScript_IsValueTrue(tSpiderValue *Value); -void SpiderScript_FreeValue(tSpiderValue *Value); -char *SpiderScript_DumpValue(tSpiderValue *Value); -// --- Operations -tSpiderValue *SpiderScript_DoOp(tSpiderValue *Left, int Operation, int bCanCast, tSpiderValue *Right); -tSpiderValue *SpiderScript_int_DoOpInt(tSpiderValue *Left, int Operation, int bCanCast, tSpiderValue *Right); -tSpiderValue *SpiderScript_int_DoOpReal(tSpiderValue *Left, int Operation, int bCanCast, tSpiderValue *Right); -tSpiderValue *SpiderScript_int_DoOpString(tSpiderValue *Left, int Operation, int bCanCast, tSpiderValue *Right); - - -// === CODE === -/** - * \brief Dereference a created object - */ -void SpiderScript_DereferenceValue(tSpiderValue *Object) -{ - if(!Object || Object == ERRPTR) return ; - Object->ReferenceCount --; - if(Object->Type == SS_DATATYPE_OBJECT) { - } - if( Object->ReferenceCount == 0 ) - { - switch( (enum eSpiderScript_DataTypes) Object->Type ) - { - case SS_DATATYPE_OBJECT: - Object->Object->ReferenceCount --; - if(Object->Object->ReferenceCount == 0) { - Object->Object->Type->Destructor( Object->Object ); - } - Object->Object = NULL; - break; - - case SS_DATATYPE_OPAQUE: - Object->Opaque.Destroy( Object->Opaque.Data ); - break; - default: - break; - } - free(Object); - } -} - -/** - * \brief Reference a value - */ -void SpiderScript_ReferenceValue(tSpiderValue *Object) -{ - if(!Object || Object == ERRPTR) return ; - Object->ReferenceCount ++; -} - -/** - * \brief Allocate and initialise a SpiderScript object - */ -tSpiderObject *SpiderScript_AllocateObject(tSpiderObjectDef *Class, int ExtraBytes) -{ - int size = sizeof(tSpiderObject) + Class->NAttributes * sizeof(tSpiderValue*) + ExtraBytes; - tSpiderObject *ret = malloc(size); - - ret->Type = Class; - ret->ReferenceCount = 1; - ret->OpaqueData = &ret->Attributes[ Class->NAttributes ]; - memset( ret->Attributes, 0, Class->NAttributes * sizeof(tSpiderValue*) ); - - return ret; -} - -/** - * \brief Create an integer object - */ -tSpiderValue *SpiderScript_CreateInteger(uint64_t Value) -{ - tSpiderValue *ret = malloc( sizeof(tSpiderValue) ); - ret->Type = SS_DATATYPE_INTEGER; - ret->ReferenceCount = 1; - ret->Integer = Value; - return ret; -} - -/** - * \brief Create an real number object - */ -tSpiderValue *SpiderScript_CreateReal(double Value) -{ - tSpiderValue *ret = malloc( sizeof(tSpiderValue) ); - ret->Type = SS_DATATYPE_REAL; - ret->ReferenceCount = 1; - ret->Real = Value; - return ret; -} - -/** - * \brief Create an string object - */ -tSpiderValue *SpiderScript_CreateString(int Length, const char *Data) -{ - tSpiderValue *ret = malloc( sizeof(tSpiderValue) + Length + 1 ); - ret->Type = SS_DATATYPE_STRING; - ret->ReferenceCount = 1; - ret->String.Length = Length; - if( Data ) - memcpy(ret->String.Data, Data, Length); - else - memset(ret->String.Data, 0, Length); - ret->String.Data[Length] = '\0'; - return ret; -} - -/** - * \brief Concatenate two strings - */ -tSpiderValue *SpiderScript_StringConcat(const tSpiderValue *Str1, const tSpiderValue *Str2) -{ - int newLen = 0; - tSpiderValue *ret; - - if( Str1 && Str1->Type != SS_DATATYPE_STRING) - return NULL; - if( Str2 && Str2->Type != SS_DATATYPE_STRING) - return NULL; - - if(Str1) newLen += Str1->String.Length; - if(Str2) newLen += Str2->String.Length; - ret = malloc( sizeof(tSpiderValue) + newLen + 1 ); - ret->Type = SS_DATATYPE_STRING; - ret->ReferenceCount = 1; - ret->String.Length = newLen; - if(Str1) - memcpy(ret->String.Data, Str1->String.Data, Str1->String.Length); - if(Str2) { - if(Str1) - memcpy(ret->String.Data+Str1->String.Length, Str2->String.Data, Str2->String.Length); - else - memcpy(ret->String.Data, Str2->String.Data, Str2->String.Length); - } - ret->String.Data[ newLen ] = '\0'; - return ret; -} - -/** - * \brief Cast one object to another - * \brief Type Destination type - * \brief Source Input data - */ -tSpiderValue *SpiderScript_CastValueTo(int Type, tSpiderValue *Source) -{ - tSpiderValue *ret = ERRPTR; - int len = 0; - - if( !Source ) - { - switch(Type) - { - case SS_DATATYPE_INTEGER: return SpiderScript_CreateInteger(0); - case SS_DATATYPE_REAL: return SpiderScript_CreateReal(0); - case SS_DATATYPE_STRING: return SpiderScript_CreateString(4, "null"); - } - return NULL; - } - - // Check if anything needs to be done - if( Source->Type == Type ) { - SpiderScript_ReferenceValue(Source); - return Source; - } - - // Debug - #if 0 - { - printf("Casting %i ", Source->Type); - switch(Source->Type) - { - case SS_DATATYPE_INTEGER: printf("0x%lx", Source->Integer); break; - case SS_DATATYPE_STRING: printf("\"%s\"", Source->String.Data); break; - case SS_DATATYPE_REAL: printf("%f", Source->Real); break; - default: break; - } - printf(" to %i\n", Type); - } - #endif - - // Object casts - #if 0 - if( Source->Type == SS_DATATYPE_OBJECT ) - { - const char *name = NULL; - switch(Type) - { - case SS_DATATYPE_INTEGER: name = "cast Integer"; break; - case SS_DATATYPE_REAL: name = "cast Real"; break; - case SS_DATATYPE_STRING: name = "cast String"; break; - case SS_DATATYPE_ARRAY: name = "cast Array"; break; - default: - AST_RuntimeError(NULL, "Invalid cast to %i from Object", Type); - return ERRPTR; - } - if( fcnname ) - { - ret = Object_ExecuteMethod(Left->Object, fcnname, Right); - if( ret != ERRPTR ) - return ret; - // Fall through and try casting (which will usually fail) - } - } - #endif - - switch( (enum eSpiderScript_DataTypes)Type ) - { - case SS_DATATYPE_UNDEF: - case SS_DATATYPE_ARRAY: - case SS_DATATYPE_OPAQUE: - AST_RuntimeError(NULL, "Invalid cast to %i", Type); - return ERRPTR; - case SS_DATATYPE_OBJECT: - // TODO: - AST_RuntimeError(NULL, "Invalid cast to %i", Type); - return ERRPTR; - - case SS_DATATYPE_INTEGER: - ret = malloc(sizeof(tSpiderValue)); - ret->Type = SS_DATATYPE_INTEGER; - ret->ReferenceCount = 1; - switch(Source->Type) - { - case SS_DATATYPE_INTEGER: break; // Handled above - case SS_DATATYPE_STRING: ret->Integer = atoi(Source->String.Data); break; - case SS_DATATYPE_REAL: ret->Integer = Source->Real; break; - default: - AST_RuntimeError(NULL, "Invalid cast from %i to Integer", Source->Type); - free(ret); - ret = ERRPTR; - break; - } - break; - - case SS_DATATYPE_REAL: - ret = malloc(sizeof(tSpiderValue)); - ret->Type = SS_DATATYPE_REAL; - ret->ReferenceCount = 1; - switch(Source->Type) - { - case SS_DATATYPE_STRING: ret->Real = atof(Source->String.Data); break; - case SS_DATATYPE_INTEGER: ret->Real = Source->Integer; break; - default: - AST_RuntimeError(NULL, "Invalid cast from %i to Real", Source->Type); - free(ret); - ret = ERRPTR; - break; - } - break; - - case SS_DATATYPE_STRING: - switch(Source->Type) - { - case SS_DATATYPE_INTEGER: len = snprintf(NULL, 0, "%li", Source->Integer); break; - case SS_DATATYPE_REAL: len = snprintf(NULL, 0, "%g", Source->Real); break; - default: break; - } - ret = malloc(sizeof(tSpiderValue) + len + 1); - ret->Type = SS_DATATYPE_STRING; - ret->ReferenceCount = 1; - ret->String.Length = len; - switch(Source->Type) - { - case SS_DATATYPE_INTEGER: sprintf(ret->String.Data, "%li", Source->Integer); break; - case SS_DATATYPE_REAL: - sprintf(ret->String.Data, "%g", Source->Real); break; - default: - AST_RuntimeError(NULL, "Invalid cast from %i to String", Source->Type); - free(ret); - ret = ERRPTR; - break; - } - break; - - default: - AST_RuntimeError(NULL, "BUG - BUG REPORT: Unimplemented cast target %i", Type); - ret = ERRPTR; - break; - } - - return ret; -} - -/** - * \brief Condenses a value down to a boolean - */ -int SpiderScript_IsValueTrue(tSpiderValue *Value) -{ - if( Value == ERRPTR ) return 0; - if( Value == NULL ) return 0; - - switch( (enum eSpiderScript_DataTypes)Value->Type ) - { - case SS_DATATYPE_UNDEF: - return 0; - - case SS_DATATYPE_INTEGER: - return !!Value->Integer; - - case SS_DATATYPE_REAL: - return (-.5f < Value->Real && Value->Real < 0.5f); - - case SS_DATATYPE_STRING: - return Value->String.Length > 0; - - case SS_DATATYPE_OBJECT: - return Value->Object != NULL; - - case SS_DATATYPE_OPAQUE: - return Value->Opaque.Data != NULL; - - case SS_DATATYPE_ARRAY: - return Value->Array.Length > 0; - default: - AST_RuntimeError(NULL, "Unknown type %i in SpiderScript_IsValueTrue", Value->Type); - return 0; - } - return 0; -} - -/** - * \brief Free a value - * \note Just calls Object_Dereference - */ -void SpiderScript_FreeValue(tSpiderValue *Value) -{ - SpiderScript_DereferenceValue(Value); -} - -/** - * \brief Dump a value into a string - * \return Heap string - */ -char *SpiderScript_DumpValue(tSpiderValue *Value) -{ - char *ret; - if( Value == ERRPTR ) - return strdup("ERRPTR"); - if( Value == NULL ) - return strdup("null"); - - switch( (enum eSpiderScript_DataTypes)Value->Type ) - { - case SS_DATATYPE_UNDEF: return strdup("undefined"); - - case SS_DATATYPE_INTEGER: - ret = malloc( sizeof(Value->Integer)*2 + 3 ); - sprintf(ret, "0x%lx", Value->Integer); - return ret; - - case SS_DATATYPE_REAL: - ret = malloc( sprintf(NULL, "%f", Value->Real) + 1 ); - sprintf(ret, "%f", Value->Real); - return ret; - - case SS_DATATYPE_STRING: - ret = malloc( Value->String.Length + 3 ); - ret[0] = '"'; - strcpy(ret+1, Value->String.Data); - ret[Value->String.Length+1] = '"'; - ret[Value->String.Length+2] = '\0'; - return ret; - - case SS_DATATYPE_OBJECT: - ret = malloc( sprintf(NULL, "{%s *%p}", Value->Object->Type->Name, Value->Object) + 1 ); - sprintf(ret, "{%s *%p}", Value->Object->Type->Name, Value->Object); - return ret; - - case SS_DATATYPE_OPAQUE: - ret = malloc( sprintf(NULL, "*%p", Value->Opaque.Data) + 1 ); - sprintf(ret, "*%p", Value->Opaque.Data); - return ret; - - case SS_DATATYPE_ARRAY: - return strdup("Array"); - - default: - AST_RuntimeError(NULL, "Unknown type %i in Object_Dump", Value->Type); - return NULL; - } - -} - -// --- -tSpiderValue *SpiderScript_DoOp(tSpiderValue *Left, int Operation, int bCanCast, tSpiderValue *Right) -{ - switch(Left->Type) - { - case SS_DATATYPE_INTEGER: - return SpiderScript_int_DoOpInt(Left, Operation, bCanCast, Right); - } - return NULL; -} - -tSpiderValue *SpiderScript_int_DoOpInt(tSpiderValue *Left, int Operation, int bCanCast, tSpiderValue *Right) -{ - tSpiderValue *oldright = Right; - tSpiderValue *ret = NULL; - int64_t rv; - - // Casting - if(Right && Right->Type != SS_DATATYPE_INTEGER) { - if(!bCanCast) return ERRPTR; - Right = SpiderScript_CastValueTo(Right, SS_DATATYPE_INTEGER); - } - - // Do the operation - switch(Operation) - { - case SS_VALUEOP_NEGATE: - if(Right) ret = ERRPTR; - else rv = -Left->Integer; - break; - case SS_VALUEOP_ADD: - if(!Right) ret = ERRPTR; - else rv = Left->Integer + Right->Integer; - break; - } - - // Delete temporary value - if( Right != oldright ) - SpiderScript_DereferenceValue(Right); - - // Return error if signaled - if(ret == ERRPTR) - return ERRPTR; - - // Reuse `Left` if possible, to reduce mallocs - if(Left->ReferenceCount == 1) { - SpiderScript_ReferenceValue(Left); - Left->Integer = rv; - return Left; - } - else { - return SpiderScript_CreateInteger(rv); - } -} - diff --git a/Usermode/include/spiderscript.h b/Usermode/include/spiderscript.h deleted file mode 100644 index e1dc5078..00000000 --- a/Usermode/include/spiderscript.h +++ /dev/null @@ -1,321 +0,0 @@ -/* - * - */ -#ifndef _SPIDERSCRIPT_H_ -#define _SPIDERSCRIPT_H_ - -#include - -#define ERRPTR ((void*)((intptr_t)0-1)) - -/** - * \brief Opaque script handle - */ -typedef struct sSpiderScript tSpiderScript; - -typedef struct sSpiderVariant tSpiderVariant; -typedef struct sSpiderNamespace tSpiderNamespace; -typedef struct sSpiderFunction tSpiderFunction; -typedef struct sSpiderValue tSpiderValue; -typedef struct sSpiderObjectDef tSpiderObjectDef; -typedef struct sSpiderObject tSpiderObject; - - -/** - * \brief SpiderScript Variable Datatypes - * \todo Expand the descriptions - */ -enum eSpiderScript_DataTypes -{ - /** - * \brief Undefined data - * \note Default type of an undefined dynamic variable - */ - SS_DATATYPE_UNDEF, - /** - * \brief Dynamically typed variable - * \note Used to dentote a non-fixed type for function parameters - */ - SS_DATATYPE_DYNAMIC, - /** - * \brief Opaque Data Pointer - * - * Opaque data types are used for resource handles or for system buffers. - */ - SS_DATATYPE_OPAQUE, - /** - * \brief Object reference - * - * A reference to a SpiderScript class instance. Can be accessed - * using the -> operator. - */ - SS_DATATYPE_OBJECT, - /** - * \brief Array data type - */ - SS_DATATYPE_ARRAY, - /** - * \brief Integer datatype - * - * 64-bit integer - */ - SS_DATATYPE_INTEGER, - SS_DATATYPE_REAL, //!< Real Number (double) - SS_DATATYPE_STRING, //!< String - NUM_SS_DATATYPES -}; - -enum eSpiderValueOps -{ - SS_VALUEOP_NOP, - - SS_VALUEOP_ADD, - SS_VALUEOP_SUBTRACT, - SS_VALUEOP_NEGATE, - SS_VALUEOP_MULIPLY, - SS_VALUEOP_DIVIDE, - SS_VALUEOP_MODULO, - - SS_VALUEOP_BITNOT, - SS_VALUEOP_BITAND, - SS_VALUEOP_BITOR, - SS_VALUEOP_BITXOR, - - SS_VALUEOP_SHIFTLEFT, - SS_VALUEOP_SHIFTRIGHT, - SS_VALUEOP_ROTATELEFT -}; - -/** - * \brief Namespace definition - */ -struct sSpiderNamespace -{ - tSpiderNamespace *Next; - - tSpiderNamespace *FirstChild; - - tSpiderFunction *Functions; - - tSpiderObjectDef *Classes; - - int NConstants; //!< Number of constants - tSpiderValue *Constants; //!< Number of constants - - const char Name[]; -}; - -/** - * \brief Variant of SpiderScript - */ -struct sSpiderVariant -{ - const char *Name; // Just for debug - - int bDyamicTyped; //!< Use dynamic typing - int bImplicitCasts; //!< Allow implicit casts (casts to lefthand side) - - tSpiderFunction *Functions; //!< Functions (Linked List) - - int NConstants; //!< Number of constants - tSpiderValue *Constants; //!< Number of constants - - tSpiderNamespace RootNamespace; -}; - -/** - * \brief SpiderScript data object - */ -struct sSpiderValue -{ - enum eSpiderScript_DataTypes Type; //!< Variable type - int ReferenceCount; //!< Reference count - - union { - int64_t Integer; //!< Integer data - double Real; //!< Real Number data - /** - * \brief String data - */ - struct { - int Length; //!< Length - char Data[]; //!< Actual string (\a Length bytes) - } String; - /** - * \brief Variable data - */ - struct { - int Length; //!< Length of the array - tSpiderValue *Items[]; //!< Array elements (\a Length long) - } Array; - - /** - * \brief Opaque data - */ - struct { - void *Data; //!< Data (can be anywhere) - void (*Destroy)(void *Data); //!< Called on GC - } Opaque; - - /** - * \brief Object Instance - */ - tSpiderObject *Object; - }; -}; - -/** - * \brief Object Definition - * - * Internal representation of an arbitary object. - */ -struct sSpiderObjectDef -{ - /** - */ - struct sSpiderObjectDef *Next; //!< Internal linked list - /** - * \brief Object type name - */ - const char * const Name; - /** - * \brief Construct an instance of the object - * \param NArgs Number of arguments - * \param Args Argument array - * \return Pointer to an object instance (which must be fully valid) - * \retval NULL Invalid parameter (usually, actually just a NULL value) - * \retval ERRPTR Invalid parameter count - */ - tSpiderObject *(*Constructor)(int NArgs, tSpiderValue **Args); - - /** - * \brief Clean up and destroy the object - * \param This Object instace - * \note The object pointer (\a This) should be invalidated and freed - * by this function. - */ - void (*Destructor)(tSpiderObject *This); - - tSpiderFunction *Methods; //!< Method Definitions (linked list) - - int NAttributes; //!< Number of attributes - - //! Attribute definitions - struct { - const char *Name; //!< Attribute Name - int bReadOnly; //!< Allow writes to the attribute? - } AttributeDefs[]; -}; - -/** - * \brief Object Instance - */ -struct sSpiderObject -{ - tSpiderObjectDef *Type; //!< Object Type - int ReferenceCount; //!< Number of references - void *OpaqueData; //!< Pointer to the end of the \a Attributes array - tSpiderValue *Attributes[]; //!< Attribute Array -}; - -/** - * \brief Represents a function avaliable to a script - */ -struct sSpiderFunction -{ - /** - * \brief Next function in list - */ - struct sSpiderFunction *Next; - - /** - * \brief Function name - */ - const char *Name; - /** - * \brief Function handler - */ - tSpiderValue *(*Handler)(tSpiderScript *Script, int nParams, tSpiderValue **Parameters); - /** - * \brief Argument types - * - * Zero or -1 terminated array of \a eSpiderScript_DataTypes. - * If the final entry is zero, the function has a fixed number of - * parameters, if the final entry is -1, the function has a variable - * number of arguments. - */ - int ArgTypes[]; // Zero (or -1) terminated array of parameter types -}; - - -// === FUNCTIONS === -/** - * \brief Parse a file into a script - * \param Variant Variant structure - * \param Filename File to parse - * \return Script suitable for execution - */ -extern tSpiderScript *SpiderScript_ParseFile(tSpiderVariant *Variant, const char *Filename); -/** - * \brief Execute a function from a script - * \param Script Script to run - * \param Function Name of function to run ("" for the 'main') - * \return Return value - */ -extern tSpiderValue *SpiderScript_ExecuteFunction(tSpiderScript *Script, - tSpiderNamespace *Namespace, const char *Function, - int NArguments, tSpiderValue **Arguments - ); -/** - * \brief Execute an object method - */ -extern tSpiderValue *SpiderScript_ExecuteMethod(tSpiderScript *Script, - tSpiderObject *Object, const char *MethodName, - int NArguments, tSpiderValue **Arguments - ); -/** - * \brief Creates an object instance - */ -extern tSpiderValue *SpiderScript_CreateObject(tSpiderScript *Script, - tSpiderNamespace *Namespace, const char *ClassName, - int NArguments, tSpiderValue **Arguments - ); - -/** - * \brief Convert a script to bytecode and save to a file - */ -extern int SpiderScript_SaveBytecode(tSpiderScript *Script, const char *DestFile); -/** - * \brief Save the AST of a script to a file - */ -extern int SpiderScript_SaveAST(tSpiderScript *Script, const char *Filename); - -/** - * \brief Free a script - * \param Script Script structure to free - */ -extern void SpiderScript_Free(tSpiderScript *Script); - -extern tSpiderObject *SpiderScript_AllocateObject(tSpiderObjectDef *Class, int ExtraBytes); - -/** - * \name tSpiderValue Manipulation functions - * \{ - */ -extern void SpiderScript_DereferenceValue(tSpiderValue *Object); -extern void SpiderScript_ReferenceValue(tSpiderValue *Object); -extern tSpiderValue *SpiderScript_CreateInteger(uint64_t Value); -extern tSpiderValue *SpiderScript_CreateReal(double Value); -extern tSpiderValue *SpiderScript_CreateString(int Length, const char *Data); -extern tSpiderValue *SpiderScript_StringConcat(const tSpiderValue *Str1, const tSpiderValue *Str2); -extern tSpiderValue *SpiderScript_CastValueTo(int Type, tSpiderValue *Source); -extern int SpiderScript_IsValueTrue(tSpiderValue *Value); -extern void SpiderScript_FreeValue(tSpiderValue *Value); -extern char *SpiderScript_DumpValue(tSpiderValue *Value); - -extern tSpiderValue *SpiderScript_DoOp(tSpiderValue *Left, enum eSpiderValueOps Op, int bCanCast, tSpiderValue *Right); -/** - * \} - */ - -#endif