1
0
forked from Mirror/wren

Merge remote-tracking branch 'munificent/master'

This commit is contained in:
Bryan C
2015-03-16 10:56:14 -04:00
7 changed files with 196 additions and 121 deletions

View File

@ -15,6 +15,8 @@
29205C9D1AB4E6430073018D /* wren_utils.c in Sources */ = {isa = PBXBuildFile; fileRef = 29205C961AB4E6430073018D /* wren_utils.c */; };
29205C9E1AB4E6430073018D /* wren_value.c in Sources */ = {isa = PBXBuildFile; fileRef = 29205C971AB4E6430073018D /* wren_value.c */; };
29205C9F1AB4E6430073018D /* wren_vm.c in Sources */ = {isa = PBXBuildFile; fileRef = 29205C981AB4E6430073018D /* wren_vm.c */; };
29C8A92F1AB71C1C00DEC81D /* io.c in Sources */ = {isa = PBXBuildFile; fileRef = 29C8A92E1AB71C1C00DEC81D /* io.c */; };
29C8A9331AB71FFF00DEC81D /* vm.c in Sources */ = {isa = PBXBuildFile; fileRef = 29C8A9311AB71FFF00DEC81D /* vm.c */; };
/* End PBXBuildFile section */
/* Begin PBXCopyFilesBuildPhase section */
@ -48,6 +50,10 @@
29205CA71AB4E65E0073018D /* wren_value.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = wren_value.h; path = ../../src/vm/wren_value.h; sourceTree = "<group>"; };
29205CA81AB4E65E0073018D /* wren_vm.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = wren_vm.h; path = ../../src/vm/wren_vm.h; sourceTree = "<group>"; };
29AB1F061816E3AD004B501E /* wren */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = wren; sourceTree = BUILT_PRODUCTS_DIR; };
29C8A92E1AB71C1C00DEC81D /* io.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = io.c; path = ../../src/cli/io.c; sourceTree = "<group>"; };
29C8A9301AB71C3300DEC81D /* io.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = io.h; path = ../../src/cli/io.h; sourceTree = "<group>"; };
29C8A9311AB71FFF00DEC81D /* vm.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = vm.c; path = ../../src/cli/vm.c; sourceTree = "<group>"; };
29C8A9321AB71FFF00DEC81D /* vm.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = vm.h; path = ../../src/cli/vm.h; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@ -86,7 +92,11 @@
29205CA91AB4E67B0073018D /* cli */ = {
isa = PBXGroup;
children = (
29C8A9301AB71C3300DEC81D /* io.h */,
29C8A92E1AB71C1C00DEC81D /* io.c */,
29205C8E1AB4E5C90073018D /* main.c */,
29C8A9321AB71FFF00DEC81D /* vm.h */,
29C8A9311AB71FFF00DEC81D /* vm.c */,
);
name = cli;
sourceTree = "<group>";
@ -170,11 +180,13 @@
files = (
29205C991AB4E6430073018D /* wren_compiler.c in Sources */,
29205C9A1AB4E6430073018D /* wren_core.c in Sources */,
29C8A9331AB71FFF00DEC81D /* vm.c in Sources */,
29205C9B1AB4E6430073018D /* wren_debug.c in Sources */,
29205C9C1AB4E6430073018D /* wren_io.c in Sources */,
29205C9D1AB4E6430073018D /* wren_utils.c in Sources */,
29205C9E1AB4E6430073018D /* wren_value.c in Sources */,
29205C9F1AB4E6430073018D /* wren_vm.c in Sources */,
29C8A92F1AB71C1C00DEC81D /* io.c in Sources */,
29205C8F1AB4E5C90073018D /* main.c in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;

77
src/cli/io.c Normal file
View File

@ -0,0 +1,77 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "io.h"
char const* rootDirectory = NULL;
// Reads the contents of the file at [path] and returns it as a heap allocated
// string.
//
// Returns `NULL` if the path could not be found. Exits if it was found but
// could not be read.
char* readFile(const char* path)
{
FILE* file = fopen(path, "rb");
if (file == NULL) return NULL;
// Find out how big the file is.
fseek(file, 0L, SEEK_END);
size_t fileSize = ftell(file);
rewind(file);
// Allocate a buffer for it.
char* buffer = (char*)malloc(fileSize + 1);
if (buffer == NULL)
{
fprintf(stderr, "Could not read file \"%s\".\n", path);
exit(74);
}
// Read the entire file.
size_t bytesRead = fread(buffer, sizeof(char), fileSize, file);
if (bytesRead < fileSize)
{
fprintf(stderr, "Could not read file \"%s\".\n", path);
exit(74);
}
// Terminate the string.
buffer[bytesRead] = '\0';
fclose(file);
return buffer;
}
void setRootDirectory(const char* path)
{
rootDirectory = path;
}
char* readModule(WrenVM* vm, const char* module)
{
// The module path is relative to the root directory and with ".wren".
size_t rootLength = rootDirectory == NULL ? 0 : strlen(rootDirectory);
size_t moduleLength = strlen(module);
size_t pathLength = rootLength + moduleLength + 5;
char* path = (char*)malloc(pathLength + 1);
if (rootDirectory != NULL)
{
memcpy(path, rootDirectory, rootLength);
}
memcpy(path + rootLength, module, moduleLength);
memcpy(path + rootLength + moduleLength, ".wren", 5);
path[pathLength] = '\0';
char* file = readFile(path);
if (file == NULL)
{
free(path);
return NULL;
}
return file;
}

25
src/cli/io.h Normal file
View File

@ -0,0 +1,25 @@
#ifndef io_h
#define io_h
#include "wren.h"
// Simple IO functions.
// Reads the contents of the file at [path] and returns it as a heap allocated
// string.
//
// Returns `NULL` if the path could not be found. Exits if it was found but
// could not be read.
char* readFile(const char* path);
// Sets the root directory that modules are resolved relative to.
void setRootDirectory(const char* path);
// Attempts to read the source for [module] relative to the current root
// directory.
//
// Returns it if found, or NULL if the module could not be found. Exits if the
// module was found but could not be read.
char* readModule(WrenVM* vm, const char* module);
#endif

View File

@ -1,120 +1,19 @@
#include <stdarg.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "io.h"
#include "vm.h"
#include "wren.h"
#define MAX_LINE_LENGTH 1024 // TODO: Something less arbitrary.
#define MAX_PATH_LENGTH 2024 // TODO: Something less arbitrary.
char rootDirectory[MAX_PATH_LENGTH];
// Reads the contents of the file at [path] and returns it as a heap allocated
// string.
//
// Returns `NULL` if the path could not be found. Exits if it was found but
// could not be read.
static char* readFile(const char* path)
static int runRepl()
{
FILE* file = fopen(path, "rb");
if (file == NULL) return NULL;
WrenVM* vm = createVM();
// Find out how big the file is.
fseek(file, 0L, SEEK_END);
size_t fileSize = ftell(file);
rewind(file);
// Allocate a buffer for it.
char* buffer = (char*)malloc(fileSize + 1);
if (buffer == NULL)
{
fprintf(stderr, "Could not read file \"%s\".\n", path);
exit(74);
}
// Read the entire file.
size_t bytesRead = fread(buffer, sizeof(char), fileSize, file);
if (bytesRead < fileSize)
{
fprintf(stderr, "Could not read file \"%s\".\n", path);
exit(74);
}
// Terminate the string.
buffer[bytesRead] = '\0';
fclose(file);
return buffer;
}
static char* readModule(WrenVM* vm, const char* module)
{
// The module path is relative to the root directory and with ".wren".
size_t rootLength = strlen(rootDirectory);
size_t moduleLength = strlen(module);
size_t pathLength = rootLength + moduleLength + 5;
char* path = (char*)malloc(pathLength + 1);
memcpy(path, rootDirectory, rootLength);
memcpy(path + rootLength, module, moduleLength);
memcpy(path + rootLength + moduleLength, ".wren", 5);
path[pathLength] = '\0';
char* file = readFile(path);
if (file == NULL)
{
free(path);
return NULL;
}
return file;
}
static int runFile(WrenVM* vm, const char* path)
{
// Use the directory where the file is as the root to resolve imports
// relative to.
const char* lastSlash = strrchr(path, '/');
if (lastSlash != NULL)
{
memcpy(rootDirectory, path, lastSlash - path + 1);
rootDirectory[lastSlash - path + 1] = '\0';
}
char* source = readFile(path);
if (source == NULL)
{
fprintf(stderr, "Could not find file \"%s\".\n", path);
exit(66);
}
int result;
switch (wrenInterpret(vm, path, source))
{
case WREN_RESULT_SUCCESS: result = 0; break;
case WREN_RESULT_COMPILE_ERROR: result = 65; break; // EX_DATAERR.
case WREN_RESULT_RUNTIME_ERROR: result = 70; break; // EX_SOFTWARE.
default:
// Unreachable.
result = 255;
break;
}
wrenFreeVM(vm);
free(source);
return result;
}
static int runRepl(WrenVM* vm)
{
printf("\\\\/\"-\n");
printf(" \\_/ wren v0.0.0\n");
// Import relative to the current directory.
rootDirectory[0] = '\0';
char line[MAX_LINE_LENGTH];
for (;;)
@ -147,20 +46,14 @@ int main(int argc, const char* argv[])
return 64; // EX_USAGE.
}
WrenConfiguration config;
if (argc == 1)
{
runRepl();
}
else if (argc == 2)
{
runFile(argv[1]);
}
config.loadModuleFn = readModule;
// Since we're running in a standalone process, be generous with memory.
config.initialHeapSize = 1024 * 1024 * 100;
// Use defaults for these.
config.reallocateFn = NULL;
config.minHeapSize = 0;
config.heapGrowthPercent = 0;
WrenVM* vm = wrenNewVM(&config);
if (argc == 1) return runRepl(vm);
if (argc == 2) return runFile(vm, argv[1]);
return 0;
}

54
src/cli/vm.c Normal file
View File

@ -0,0 +1,54 @@
#include <stdio.h>
#include <string.h>
#include "io.h"
#include "vm.h"
WrenVM* createVM()
{
WrenConfiguration config;
config.loadModuleFn = readModule;
// Since we're running in a standalone process, be generous with memory.
config.initialHeapSize = 1024 * 1024 * 100;
// Use defaults for these.
config.reallocateFn = NULL;
config.minHeapSize = 0;
config.heapGrowthPercent = 0;
return wrenNewVM(&config);
}
void runFile(const char* path)
{
// Use the directory where the file is as the root to resolve imports
// relative to.
const char* lastSlash = strrchr(path, '/');
if (lastSlash != NULL)
{
char* root = (char*)malloc(lastSlash - path + 2);
memcpy(root, path, lastSlash - path + 1);
root[lastSlash - path + 1] = '\0';
setRootDirectory(root);
}
char* source = readFile(path);
if (source == NULL)
{
fprintf(stderr, "Could not find file \"%s\".\n", path);
exit(66);
}
WrenVM* vm = createVM();
WrenInterpretResult result = wrenInterpret(vm, path, source);
wrenFreeVM(vm);
free(source);
// Exit with an error code if the script failed.
if (result == WREN_RESULT_COMPILE_ERROR) exit(65); // EX_DATAERR.
if (result == WREN_RESULT_RUNTIME_ERROR) exit(70); // EX_SOFTWARE.
}

14
src/cli/vm.h Normal file
View File

@ -0,0 +1,14 @@
#ifndef vm_h
#define vm_h
#include "wren.h"
// Creates a new Wren VM with the CLI's module loader and other configuration.
WrenVM* createVM();
// Executes the Wren script at [path] in a new VM.
//
// Exits if the script failed or could not be loaded.
void runFile(const char* path);
#endif

View File

@ -48,7 +48,7 @@ static void dumpObject(Obj* obj)
case OBJ_LIST: printf("[list %p]", obj); break;
case OBJ_MAP: printf("[map %p]", obj); break;
case OBJ_MODULE: printf("[module %p]", obj); break;
case OBJ_RANGE: printf("[fn %p]", obj); break;
case OBJ_RANGE: printf("[range %p]", obj); break;
case OBJ_STRING: printf("%s", ((ObjString*)obj)->value); break;
case OBJ_UPVALUE: printf("[upvalue %p]", obj); break;
default: printf("[unknown object]"); break;