mirror of
				https://github.com/janet-lang/janet
				synced 2025-10-31 15:43:01 +00:00 
			
		
		
		
	Make some changes and begin work on macros.
This commit is contained in:
		
							
								
								
									
										24
									
								
								compile.c
									
									
									
									
									
								
							
							
						
						
									
										24
									
								
								compile.c
									
									
									
									
									
								
							| @@ -1185,3 +1185,27 @@ Func * CompilerCompile(Compiler * c, Value form) { | |||||||
|         return func; |         return func; | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | /* Macro expansion. Macro expansion happens prior to the compilation process | ||||||
|  |  * and is completely separate. This allows the compilation to not have to worry | ||||||
|  |  * about garbage collection and other issues that would complicate both the | ||||||
|  |  * runtime and the compilation. */ | ||||||
|  | int CompileMacroExpand(VM * vm, Value x, Dictionary * macros, Value * out) { | ||||||
|  |     while (x.type == TYPE_FORM) { | ||||||
|  |         Array * form = x.data.array; | ||||||
|  |         Value sym, macroFn; | ||||||
|  |         if (form->count == 0) break; | ||||||
|  |         sym = form->data[0]; | ||||||
|  |         macroFn = DictGet(macros, sym); | ||||||
|  |         if (macroFn.type != TYPE_FUNCTION && macroFn.type != TYPE_CFUNCTION) break; | ||||||
|  |         VMLoad(vm, macroFn); | ||||||
|  |         if (VMStart(vm)) { | ||||||
|  |             /* We encountered an error during parsing */         | ||||||
|  |             return 1;; | ||||||
|  |         } else { | ||||||
|  |             x = vm->ret; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |     *out = x; | ||||||
|  |     return 0; | ||||||
|  | } | ||||||
|   | |||||||
| @@ -15,4 +15,10 @@ void CompilerAddGlobalCFunc(Compiler * c, const char * name, CFunction f); | |||||||
| /* Compile a function that evaluates the given form. */ | /* Compile a function that evaluates the given form. */ | ||||||
| Func * CompilerCompile(Compiler * c, Value form); | Func * CompilerCompile(Compiler * c, Value form); | ||||||
|  |  | ||||||
|  | /* Macro expansion. Macro expansion happens prior to the compilation process | ||||||
|  |  * and is completely separate. This allows the compilation to not have to worry | ||||||
|  |  * about garbage collection and other issues that would complicate both the | ||||||
|  |  * runtime and the compilation. */ | ||||||
|  | int CompileMacroExpand(VM * vm, Value x, Dictionary * macros, Value * out); | ||||||
|  |  | ||||||
| #endif /* end of include guard: COMPILE_H_9VXF71HY */ | #endif /* end of include guard: COMPILE_H_9VXF71HY */ | ||||||
|   | |||||||
| @@ -127,10 +127,11 @@ struct VM { | |||||||
|     uint16_t * pc; |     uint16_t * pc; | ||||||
|     Array * thread; |     Array * thread; | ||||||
|     Value * base; |     Value * base; | ||||||
|  |     Value root; /* Global state - prevents GC cleanup */ | ||||||
|     /* Return state */ |     /* Return state */ | ||||||
|     const char * error; |     const char * error; | ||||||
|     jmp_buf jump; |     jmp_buf jump; | ||||||
|     Value tempRoot; /* Temporary GC root */ |     Value ret; /* Returned value from VMStart */ | ||||||
| }; | }; | ||||||
|  |  | ||||||
| /* Parsing */ | /* Parsing */ | ||||||
|   | |||||||
							
								
								
									
										11
									
								
								main.c
									
									
									
									
									
								
							
							
						
						
									
										11
									
								
								main.c
									
									
									
									
									
								
							| @@ -1,7 +1,6 @@ | |||||||
| #include <stdlib.h> | #include <stdlib.h> | ||||||
| #include <stdio.h> | #include <stdio.h> | ||||||
| #include "datatypes.h" | #include "datatypes.h" | ||||||
| #include "gc.h" |  | ||||||
| #include "vm.h" | #include "vm.h" | ||||||
| #include "parse.h" | #include "parse.h" | ||||||
| #include "compile.h" | #include "compile.h" | ||||||
| @@ -27,7 +26,7 @@ Value print(VM * vm) { | |||||||
| void debugRepl() { | void debugRepl() { | ||||||
|   char buffer[128] = {0}; |   char buffer[128] = {0}; | ||||||
|   const char * reader = buffer; |   const char * reader = buffer; | ||||||
|     Func * func; |   Value func; | ||||||
|   VM vm; |   VM vm; | ||||||
|   Parser p; |   Parser p; | ||||||
|   Compiler c; |   Compiler c; | ||||||
| @@ -74,7 +73,8 @@ void debugRepl() { | |||||||
|     /* Try to compile generated AST */ |     /* Try to compile generated AST */ | ||||||
|     CompilerInit(&c, &vm); |     CompilerInit(&c, &vm); | ||||||
|     CompilerAddGlobalCFunc(&c, "print", print); |     CompilerAddGlobalCFunc(&c, "print", print); | ||||||
|         func = CompilerCompile(&c, p.value); |     func.type = TYPE_FUNCTION; | ||||||
|  |     func.data.func = CompilerCompile(&c, p.value); | ||||||
|  |  | ||||||
|     /* Check for compilation errors */ |     /* Check for compilation errors */ | ||||||
|     if (c.error) { |     if (c.error) { | ||||||
| @@ -84,9 +84,6 @@ void debugRepl() { | |||||||
|       continue; |       continue; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|         /* Print the function that will be executed */ |  | ||||||
|         dasmFunc(stdout, func); |  | ||||||
|  |  | ||||||
|     /* Execute function */ |     /* Execute function */ | ||||||
|     VMLoad(&vm, func); |     VMLoad(&vm, func); | ||||||
|     if (VMStart(&vm)) { |     if (VMStart(&vm)) { | ||||||
| @@ -95,7 +92,7 @@ void debugRepl() { | |||||||
|       buffer[0] = 0; |       buffer[0] = 0; | ||||||
|       continue; |       continue; | ||||||
|     } else { |     } else { | ||||||
|             ValuePrint(vm.tempRoot, 0); |       ValuePrint(vm.ret, 0); | ||||||
|       printf("\n"); |       printf("\n"); | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|   | |||||||
							
								
								
									
										52
									
								
								vm.c
									
									
									
									
									
								
							
							
						
						
									
										52
									
								
								vm.c
									
									
									
									
									
								
							| @@ -23,13 +23,11 @@ struct StackFrame { | |||||||
| }; | }; | ||||||
|  |  | ||||||
| /* The size of a StackFrame in units of Values. */ | /* The size of a StackFrame in units of Values. */ | ||||||
| static size_t FRAME_SIZE() { | #define FRAME_SIZE ((sizeof(StackFrame) + sizeof(Value) - 1) / sizeof(Value)) | ||||||
|     return ((sizeof(StackFrame) + sizeof(Value) - 1) / sizeof(Value)); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| /* Get the stack frame pointer for a thread */ | /* Get the stack frame pointer for a thread */ | ||||||
| static StackFrame * ThreadFrame(Array * thread) { | static StackFrame * ThreadFrame(Array * thread) { | ||||||
| 	return (StackFrame *)(thread->data + thread->count - FRAME_SIZE()); |     return (StackFrame *)(thread->data + thread->count - FRAME_SIZE); | ||||||
| } | } | ||||||
|  |  | ||||||
| /* The metadata header associated with an allocated block of memory */ | /* The metadata header associated with an allocated block of memory */ | ||||||
| @@ -102,11 +100,11 @@ static void VMMark(VM * vm, Value * x) { | |||||||
|                 uint32_t i; |                 uint32_t i; | ||||||
|                 Array * thread = x->data.array; |                 Array * thread = x->data.array; | ||||||
|                 StackFrame * frame = (StackFrame *)thread->data; |                 StackFrame * frame = (StackFrame *)thread->data; | ||||||
|                 StackFrame * end = (StackFrame *)(thread->data + thread->count - FRAME_SIZE()); |                 StackFrame * end = (StackFrame *)(thread->data + thread->count - FRAME_SIZE); | ||||||
|                 GCHeader(thread)->color = vm->black; |                 GCHeader(thread)->color = vm->black; | ||||||
|                 GCHeader(thread->data)->color = vm->black; |                 GCHeader(thread->data)->color = vm->black; | ||||||
|                 while (frame <= end) { |                 while (frame <= end) { | ||||||
| 					Value * stack = (Value *)frame + FRAME_SIZE(); |                     Value * stack = (Value *)frame + FRAME_SIZE; | ||||||
|                     VMMark(vm, &frame->callee); |                     VMMark(vm, &frame->callee); | ||||||
|                     if (frame->env) |                     if (frame->env) | ||||||
|                         VMMarkFuncEnv(vm, frame->env); |                         VMMarkFuncEnv(vm, frame->env); | ||||||
| @@ -224,20 +222,23 @@ void * VMZalloc(VM * vm, uint32_t size) { | |||||||
| /* Run garbage collection */ | /* Run garbage collection */ | ||||||
| void VMCollect(VM * vm) { | void VMCollect(VM * vm) { | ||||||
|     if (vm->lock > 0) return; |     if (vm->lock > 0) return; | ||||||
|  |     /* Thread can be null */ | ||||||
|  |     if (vm->thread) { | ||||||
|         Value thread; |         Value thread; | ||||||
|         thread.type = TYPE_THREAD; |         thread.type = TYPE_THREAD; | ||||||
|         thread.data.array = vm->thread; |         thread.data.array = vm->thread; | ||||||
|         VMMark(vm, &thread); |         VMMark(vm, &thread); | ||||||
|     VMMark(vm, &vm->tempRoot); |     } | ||||||
|  |     VMMark(vm, &vm->ret); | ||||||
|  |     VMMark(vm, &vm->root); | ||||||
|     VMSweep(vm); |     VMSweep(vm); | ||||||
|     vm->nextCollection = 0; |     vm->nextCollection = 0; | ||||||
| } | } | ||||||
|  |  | ||||||
| /* Run garbage collection if needed */ | /* Run garbage collection if needed */ | ||||||
| void VMMaybeCollect(VM * vm) { | void VMMaybeCollect(VM * vm) { | ||||||
|     if (vm->nextCollection >= vm->memoryInterval) { |     if (vm->nextCollection >= vm->memoryInterval) | ||||||
|         VMCollect(vm); |         VMCollect(vm); | ||||||
|     } |  | ||||||
| } | } | ||||||
|  |  | ||||||
| /* Push a stack frame onto a thread */ | /* Push a stack frame onto a thread */ | ||||||
| @@ -251,7 +252,7 @@ static void VMThreadPush(VM * vm, Array * thread, Value callee, uint32_t size) { | |||||||
|     } else { |     } else { | ||||||
|         oldSize = 0; |         oldSize = 0; | ||||||
|     } |     } | ||||||
| 	nextCount = thread->count + oldSize + FRAME_SIZE(); |     nextCount = thread->count + oldSize + FRAME_SIZE; | ||||||
|     ArrayEnsure(vm, thread, nextCount + size); |     ArrayEnsure(vm, thread, nextCount + size); | ||||||
|     thread->count = nextCount; |     thread->count = nextCount; | ||||||
|     /* Ensure values start out as nil so as to not confuse |     /* Ensure values start out as nil so as to not confuse | ||||||
| @@ -285,7 +286,7 @@ static void VMThreadSplitStack(VM * vm, Array * thread) { | |||||||
| /* Pop the top-most stack frame from stack */ | /* Pop the top-most stack frame from stack */ | ||||||
| static void VMThreadPop(VM * vm, Array * thread) { | static void VMThreadPop(VM * vm, Array * thread) { | ||||||
|     StackFrame * frame = ThreadFrame(thread); |     StackFrame * frame = ThreadFrame(thread); | ||||||
|     uint32_t delta = FRAME_SIZE() + frame->prevSize; |     uint32_t delta = FRAME_SIZE + frame->prevSize; | ||||||
|     if (thread->count) { |     if (thread->count) { | ||||||
|         VMThreadSplitStack(vm, thread); |         VMThreadSplitStack(vm, thread); | ||||||
|     } else { |     } else { | ||||||
| @@ -744,29 +745,36 @@ uint16_t VMCountArgs(VM * vm) { | |||||||
|  |  | ||||||
| /* Initialize the VM */ | /* Initialize the VM */ | ||||||
| void VMInit(VM * vm) { | void VMInit(VM * vm) { | ||||||
|     vm->tempRoot.type = TYPE_NIL; |     vm->ret.type = TYPE_NIL; | ||||||
|  |     vm->root.type = TYPE_NIL; | ||||||
|     vm->base = NULL; |     vm->base = NULL; | ||||||
|     vm->pc = NULL; |     vm->pc = NULL; | ||||||
|     vm->error = NULL; |     vm->error = NULL; | ||||||
|     /* Garbage collection */ |     /* Garbage collection */ | ||||||
|     vm->blocks = NULL; |     vm->blocks = NULL; | ||||||
|     vm->nextCollection = 0; |     vm->nextCollection = 0; | ||||||
|     vm->memoryInterval = 1024 * 256; |     vm->memoryInterval = 0; | ||||||
|     vm->black = 0; |     vm->black = 0; | ||||||
|     vm->lock = 0; |     vm->lock = 0; | ||||||
|     /* Create new thread */ |     /* Set to empty thread */ | ||||||
|     vm->thread = ArrayNew(vm, 20); |     vm->thread = NULL; | ||||||
| } | } | ||||||
|  |  | ||||||
| /* Load a function into the VM. The function will be called with | /* Load a function into the VM. The function will be called with | ||||||
|  * no arguments when run */ |  * no arguments when run */ | ||||||
| void VMLoad(VM * vm, Func * func) { | void VMLoad(VM * vm, Value func) { | ||||||
|     Value callee; |     Array * thread = ArrayNew(vm, 100); | ||||||
|     callee.type = TYPE_FUNCTION; |     vm->thread = thread; | ||||||
|     callee.data.func = func; |     if (func.type == TYPE_FUNCTION) { | ||||||
|     vm->thread = ArrayNew(vm, 100); |         Func * fn = func.data.func; | ||||||
|     VMThreadPush(vm, vm->thread, callee, func->def->locals); |         VMThreadPush(vm, thread, func, fn->def->locals); | ||||||
|     vm->pc = func->def->byteCode; |         vm->pc = fn->def->byteCode; | ||||||
|  |     } else if (func.type == TYPE_CFUNCTION) { | ||||||
|  |         VMThreadPush(vm, thread, func, 0); | ||||||
|  |         vm->pc = NULL; | ||||||
|  |     } else { | ||||||
|  |         return; | ||||||
|  |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| /* Clear all memory associated with the VM */ | /* Clear all memory associated with the VM */ | ||||||
|   | |||||||
							
								
								
									
										11
									
								
								vm.h
									
									
									
									
									
								
							
							
						
						
									
										11
									
								
								vm.h
									
									
									
									
									
								
							| @@ -4,7 +4,7 @@ | |||||||
| #include "datatypes.h" | #include "datatypes.h" | ||||||
|  |  | ||||||
| /* Exit from the VM normally */ | /* Exit from the VM normally */ | ||||||
| #define VMExit(vm, r) ((vm)->tempRoot = (r), longjmp((vm)->jump, 1)) | #define VMExit(vm, r) ((vm)->ret = (r), longjmp((vm)->jump, 1)) | ||||||
|  |  | ||||||
| /* Bail from the VM with an error. */ | /* Bail from the VM with an error. */ | ||||||
| #define VMError(vm, e) ((vm)->error = (e), longjmp((vm)->jump, 2)) | #define VMError(vm, e) ((vm)->error = (e), longjmp((vm)->jump, 2)) | ||||||
| @@ -16,6 +16,10 @@ | |||||||
| #define VMAssert(vm, cond, e) do \ | #define VMAssert(vm, cond, e) do \ | ||||||
|     { if (!(cond)) { VMError((vm), (e)); } } while (0) |     { if (!(cond)) { VMError((vm), (e)); } } while (0) | ||||||
|  |  | ||||||
|  | /* Type assertion */ | ||||||
|  | #define VMAssertType(vm, f, type) \ | ||||||
|  |     VMAssert(vm, (f).type == (type), "Expected type " type) | ||||||
|  |  | ||||||
| /* Initialize the VM */ | /* Initialize the VM */ | ||||||
| void VMInit(VM * vm); | void VMInit(VM * vm); | ||||||
|  |  | ||||||
| @@ -23,14 +27,11 @@ void VMInit(VM * vm); | |||||||
| void VMDeinit(VM * vm); | void VMDeinit(VM * vm); | ||||||
|  |  | ||||||
| /* Load a function to be run on the VM */ | /* Load a function to be run on the VM */ | ||||||
| void VMLoad(VM * vm, Func * func); | void VMLoad(VM * vm, Value func); | ||||||
|  |  | ||||||
| /* Start running the VM */ | /* Start running the VM */ | ||||||
| int VMStart(VM * vm); | int VMStart(VM * vm); | ||||||
|  |  | ||||||
| /* Get the result after VMStart returns */ |  | ||||||
| #define VMResult(vm) ((vm)->tempRoot) |  | ||||||
|  |  | ||||||
| /* Run garbage collection */ | /* Run garbage collection */ | ||||||
| void VMCollect(VM * vm); | void VMCollect(VM * vm); | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Calvin Rose
					Calvin Rose