forked from Mirror/wren
A vertical slice of real libuv integration.
This adds a "timer" module to the CLI that provides a Timer class with a static sleep() method. Not the most exciting functionality in the world, but it requires the full hunk of libuv integration: - The CLI sets up libuv and runs the event loop. - Added a new directory src/module for CLI modules. - Updated all the make scripts to handle it. - Reorganized some other CLI code.
This commit is contained in:
8
Makefile
8
Makefile
@ -4,15 +4,15 @@
|
||||
|
||||
# Executables are built to bin/. Libraries are built to lib/.
|
||||
|
||||
LIB_UV := build/libuv/build/Release/libuv.a
|
||||
LIBUV := build/libuv/build/Release/libuv.a
|
||||
|
||||
# A normal, optimized release build for the current CPU architecture.
|
||||
release: $(LIB_UV)
|
||||
release: $(LIBUV)
|
||||
@ $(MAKE) -f script/wren.mk
|
||||
@ cp bin/wren wren # For convenience, copy the interpreter to the top level.
|
||||
|
||||
# A debug build for the current architecture.
|
||||
debug: $(LIB_UV)
|
||||
debug: $(LIBUV)
|
||||
@ $(MAKE) -f script/wren.mk MODE=debug
|
||||
|
||||
# A release build of just the VM. Does not require libuv.
|
||||
@ -33,7 +33,7 @@ all: debug release
|
||||
@ $(MAKE) -f script/wren.mk MODE=debug LANG=cpp ARCH=64
|
||||
|
||||
# Download and build libuv to a static library.
|
||||
$(LIB_UV): script/libuv.py
|
||||
$(LIBUV): script/libuv.py
|
||||
@ ./script/libuv.py
|
||||
|
||||
# Remove all build outputs and intermediate files.
|
||||
|
||||
@ -7,6 +7,8 @@
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
2901D7641B74F4050083A2C8 /* timer.c in Sources */ = {isa = PBXBuildFile; fileRef = 2901D7621B74F4050083A2C8 /* timer.c */; };
|
||||
2901D7651B74F4050083A2C8 /* timer.c in Sources */ = {isa = PBXBuildFile; fileRef = 2901D7621B74F4050083A2C8 /* timer.c */; };
|
||||
29205C8F1AB4E5C90073018D /* main.c in Sources */ = {isa = PBXBuildFile; fileRef = 29205C8E1AB4E5C90073018D /* main.c */; };
|
||||
29205C991AB4E6430073018D /* wren_compiler.c in Sources */ = {isa = PBXBuildFile; fileRef = 29205C921AB4E6430073018D /* wren_compiler.c */; };
|
||||
29205C9A1AB4E6430073018D /* wren_core.c in Sources */ = {isa = PBXBuildFile; fileRef = 29205C931AB4E6430073018D /* wren_core.c */; };
|
||||
@ -19,6 +21,22 @@
|
||||
29C0888F1B6E7F0100B00CFD /* libuv.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 29C0888E1B6E7F0100B00CFD /* libuv.a */; };
|
||||
29C8A92F1AB71C1C00DEC81D /* io.c in Sources */ = {isa = PBXBuildFile; fileRef = 29C8A92E1AB71C1C00DEC81D /* io.c */; };
|
||||
29C8A9331AB71FFF00DEC81D /* vm.c in Sources */ = {isa = PBXBuildFile; fileRef = 29C8A9311AB71FFF00DEC81D /* vm.c */; };
|
||||
29CE20181B7257720057FBA3 /* main.c in Sources */ = {isa = PBXBuildFile; fileRef = 29CE20171B7257720057FBA3 /* main.c */; };
|
||||
29CE201B1B72577C0057FBA3 /* return_bool.c in Sources */ = {isa = PBXBuildFile; fileRef = 29CE20191B72577C0057FBA3 /* return_bool.c */; };
|
||||
29CE201E1B7257840057FBA3 /* return_double.c in Sources */ = {isa = PBXBuildFile; fileRef = 29CE201C1B7257840057FBA3 /* return_double.c */; };
|
||||
29CE20211B72578C0057FBA3 /* return_null.c in Sources */ = {isa = PBXBuildFile; fileRef = 29CE201F1B72578C0057FBA3 /* return_null.c */; };
|
||||
29CE20221B72586B0057FBA3 /* io.c in Sources */ = {isa = PBXBuildFile; fileRef = 29C8A92E1AB71C1C00DEC81D /* io.c */; };
|
||||
29CE20231B72586B0057FBA3 /* vm.c in Sources */ = {isa = PBXBuildFile; fileRef = 29C8A9311AB71FFF00DEC81D /* vm.c */; };
|
||||
29CE20241B72586B0057FBA3 /* wren_compiler.c in Sources */ = {isa = PBXBuildFile; fileRef = 29205C921AB4E6430073018D /* wren_compiler.c */; };
|
||||
29CE20251B72586B0057FBA3 /* wren_core.c in Sources */ = {isa = PBXBuildFile; fileRef = 29205C931AB4E6430073018D /* wren_core.c */; };
|
||||
29CE20261B72586B0057FBA3 /* wren_debug.c in Sources */ = {isa = PBXBuildFile; fileRef = 29205C941AB4E6430073018D /* wren_debug.c */; };
|
||||
29CE20271B72586B0057FBA3 /* wren_io.c in Sources */ = {isa = PBXBuildFile; fileRef = 29205C951AB4E6430073018D /* wren_io.c */; };
|
||||
29CE20281B72586B0057FBA3 /* wren_meta.c in Sources */ = {isa = PBXBuildFile; fileRef = 29DE39511AC3A50A00987D41 /* wren_meta.c */; };
|
||||
29CE20291B72586B0057FBA3 /* wren_primitive.c in Sources */ = {isa = PBXBuildFile; fileRef = 2986F6D51ACF93BA00BCE26C /* wren_primitive.c */; };
|
||||
29CE202A1B72586B0057FBA3 /* wren_utils.c in Sources */ = {isa = PBXBuildFile; fileRef = 29205C961AB4E6430073018D /* wren_utils.c */; };
|
||||
29CE202B1B72586B0057FBA3 /* wren_value.c in Sources */ = {isa = PBXBuildFile; fileRef = 29205C971AB4E6430073018D /* wren_value.c */; };
|
||||
29CE202C1B72586B0057FBA3 /* wren_vm.c in Sources */ = {isa = PBXBuildFile; fileRef = 29205C981AB4E6430073018D /* wren_vm.c */; };
|
||||
29CE202D1B7258E20057FBA3 /* libuv.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 29C0888E1B6E7F0100B00CFD /* libuv.a */; };
|
||||
29DE39531AC3A50A00987D41 /* wren_meta.c in Sources */ = {isa = PBXBuildFile; fileRef = 29DE39511AC3A50A00987D41 /* wren_meta.c */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
@ -32,9 +50,20 @@
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 1;
|
||||
};
|
||||
29CE20081B7256660057FBA3 /* CopyFiles */ = {
|
||||
isa = PBXCopyFilesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
dstPath = /usr/share/man/man1/;
|
||||
dstSubfolderSpec = 0;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 1;
|
||||
};
|
||||
/* End PBXCopyFilesBuildPhase section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
2901D7621B74F4050083A2C8 /* timer.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = timer.c; path = ../../src/module/timer.c; sourceTree = "<group>"; };
|
||||
2901D7631B74F4050083A2C8 /* timer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = timer.h; path = ../../src/module/timer.h; sourceTree = "<group>"; };
|
||||
29205C8E1AB4E5C90073018D /* main.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = main.c; path = ../../src/cli/main.c; sourceTree = "<group>"; };
|
||||
29205C901AB4E62B0073018D /* wren.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = wren.h; path = ../../src/include/wren.h; sourceTree = "<group>"; };
|
||||
29205C921AB4E6430073018D /* wren_compiler.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = wren_compiler.c; path = ../../src/vm/wren_compiler.c; sourceTree = "<group>"; };
|
||||
@ -61,6 +90,14 @@
|
||||
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>"; };
|
||||
29CE200A1B7256660057FBA3 /* api_test */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = api_test; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
29CE20171B7257720057FBA3 /* main.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = main.c; path = ../../test/api/main.c; sourceTree = "<group>"; };
|
||||
29CE20191B72577C0057FBA3 /* return_bool.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = return_bool.c; path = ../../test/api/return_bool/return_bool.c; sourceTree = "<group>"; };
|
||||
29CE201A1B72577C0057FBA3 /* return_bool.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = return_bool.h; path = ../../test/api/return_bool/return_bool.h; sourceTree = "<group>"; };
|
||||
29CE201C1B7257840057FBA3 /* return_double.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = return_double.c; path = ../../test/api/return_double/return_double.c; sourceTree = "<group>"; };
|
||||
29CE201D1B7257840057FBA3 /* return_double.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = return_double.h; path = ../../test/api/return_double/return_double.h; sourceTree = "<group>"; };
|
||||
29CE201F1B72578C0057FBA3 /* return_null.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = return_null.c; path = ../../test/api/return_null/return_null.c; sourceTree = "<group>"; };
|
||||
29CE20201B72578C0057FBA3 /* return_null.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = return_null.h; path = ../../test/api/return_null/return_null.h; sourceTree = "<group>"; };
|
||||
29DE39511AC3A50A00987D41 /* wren_meta.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = wren_meta.c; path = ../../src/vm/wren_meta.c; sourceTree = "<group>"; };
|
||||
29DE39521AC3A50A00987D41 /* wren_meta.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = wren_meta.h; path = ../../src/vm/wren_meta.h; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
@ -74,9 +111,26 @@
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
29CE20071B7256660057FBA3 /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
29CE202D1B7258E20057FBA3 /* libuv.a in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
2901D7611B74F3E20083A2C8 /* module */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
2901D7631B74F4050083A2C8 /* timer.h */,
|
||||
2901D7621B74F4050083A2C8 /* timer.c */,
|
||||
);
|
||||
name = module;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
29205CA01AB4E6470073018D /* vm */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@ -130,7 +184,9 @@
|
||||
29C0888E1B6E7F0100B00CFD /* libuv.a */,
|
||||
29205CA91AB4E67B0073018D /* cli */,
|
||||
29205CAA1AB4E6840073018D /* include */,
|
||||
2901D7611B74F3E20083A2C8 /* module */,
|
||||
29205CA01AB4E6470073018D /* vm */,
|
||||
29CE20161B7257680057FBA3 /* api */,
|
||||
29AB1F071816E3AD004B501E /* Products */,
|
||||
);
|
||||
sourceTree = "<group>";
|
||||
@ -139,10 +195,25 @@
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
29AB1F061816E3AD004B501E /* wren */,
|
||||
29CE200A1B7256660057FBA3 /* api_test */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
29CE20161B7257680057FBA3 /* api */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
29CE20171B7257720057FBA3 /* main.c */,
|
||||
29CE20191B72577C0057FBA3 /* return_bool.c */,
|
||||
29CE201A1B72577C0057FBA3 /* return_bool.h */,
|
||||
29CE201C1B7257840057FBA3 /* return_double.c */,
|
||||
29CE201D1B7257840057FBA3 /* return_double.h */,
|
||||
29CE201F1B72578C0057FBA3 /* return_null.c */,
|
||||
29CE20201B72578C0057FBA3 /* return_null.h */,
|
||||
);
|
||||
name = api;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXNativeTarget section */
|
||||
@ -163,6 +234,23 @@
|
||||
productReference = 29AB1F061816E3AD004B501E /* wren */;
|
||||
productType = "com.apple.product-type.tool";
|
||||
};
|
||||
29CE20091B7256660057FBA3 /* api_test */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 29CE20101B7256660057FBA3 /* Build configuration list for PBXNativeTarget "api_test" */;
|
||||
buildPhases = (
|
||||
29CE20061B7256660057FBA3 /* Sources */,
|
||||
29CE20071B7256660057FBA3 /* Frameworks */,
|
||||
29CE20081B7256660057FBA3 /* CopyFiles */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
);
|
||||
name = api_test;
|
||||
productName = api_test;
|
||||
productReference = 29CE200A1B7256660057FBA3 /* api_test */;
|
||||
productType = "com.apple.product-type.tool";
|
||||
};
|
||||
/* End PBXNativeTarget section */
|
||||
|
||||
/* Begin PBXProject section */
|
||||
@ -171,6 +259,11 @@
|
||||
attributes = {
|
||||
LastUpgradeCheck = 0610;
|
||||
ORGANIZATIONNAME = "Bob Nystrom";
|
||||
TargetAttributes = {
|
||||
29CE20091B7256660057FBA3 = {
|
||||
CreatedOnToolsVersion = 6.3.2;
|
||||
};
|
||||
};
|
||||
};
|
||||
buildConfigurationList = 29AB1F011816E3AD004B501E /* Build configuration list for PBXProject "wren" */;
|
||||
compatibilityVersion = "Xcode 3.2";
|
||||
@ -185,6 +278,7 @@
|
||||
projectRoot = "";
|
||||
targets = (
|
||||
29AB1F051816E3AD004B501E /* wren */,
|
||||
29CE20091B7256660057FBA3 /* api_test */,
|
||||
);
|
||||
};
|
||||
/* End PBXProject section */
|
||||
@ -197,6 +291,7 @@
|
||||
29205C991AB4E6430073018D /* wren_compiler.c in Sources */,
|
||||
2986F6D71ACF93BA00BCE26C /* wren_primitive.c in Sources */,
|
||||
29205C9A1AB4E6430073018D /* wren_core.c in Sources */,
|
||||
2901D7641B74F4050083A2C8 /* timer.c in Sources */,
|
||||
29C8A9331AB71FFF00DEC81D /* vm.c in Sources */,
|
||||
29205C9B1AB4E6430073018D /* wren_debug.c in Sources */,
|
||||
29205C9C1AB4E6430073018D /* wren_io.c in Sources */,
|
||||
@ -209,6 +304,29 @@
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
29CE20061B7256660057FBA3 /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
29CE20221B72586B0057FBA3 /* io.c in Sources */,
|
||||
29CE20231B72586B0057FBA3 /* vm.c in Sources */,
|
||||
29CE20241B72586B0057FBA3 /* wren_compiler.c in Sources */,
|
||||
29CE20251B72586B0057FBA3 /* wren_core.c in Sources */,
|
||||
29CE20261B72586B0057FBA3 /* wren_debug.c in Sources */,
|
||||
29CE20271B72586B0057FBA3 /* wren_io.c in Sources */,
|
||||
29CE20281B72586B0057FBA3 /* wren_meta.c in Sources */,
|
||||
29CE20291B72586B0057FBA3 /* wren_primitive.c in Sources */,
|
||||
29CE202A1B72586B0057FBA3 /* wren_utils.c in Sources */,
|
||||
2901D7651B74F4050083A2C8 /* timer.c in Sources */,
|
||||
29CE202B1B72586B0057FBA3 /* wren_value.c in Sources */,
|
||||
29CE202C1B72586B0057FBA3 /* wren_vm.c in Sources */,
|
||||
29CE20181B7257720057FBA3 /* main.c in Sources */,
|
||||
29CE201B1B72577C0057FBA3 /* return_bool.c in Sources */,
|
||||
29CE201E1B7257840057FBA3 /* return_double.c in Sources */,
|
||||
29CE20211B72578C0057FBA3 /* return_null.c in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXSourcesBuildPhase section */
|
||||
|
||||
/* Begin XCBuildConfiguration section */
|
||||
@ -310,6 +428,48 @@
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
29CE200E1B7256660057FBA3 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = c99;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
"DEBUG=1",
|
||||
"$(inherited)",
|
||||
);
|
||||
GCC_WARN_PEDANTIC = NO;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
LIBRARY_SEARCH_PATHS = ../../build/libuv/build/Release;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.10;
|
||||
MTL_ENABLE_DEBUG_INFO = YES;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
USER_HEADER_SEARCH_PATHS = ../../build/libuv/include;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
29CE200F1B7256660057FBA3 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = c99;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_WARN_PEDANTIC = NO;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
LIBRARY_SEARCH_PATHS = ../../build/libuv/build/Release;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.10;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
USER_HEADER_SEARCH_PATHS = ../../build/libuv/include;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
/* End XCBuildConfiguration section */
|
||||
|
||||
/* Begin XCConfigurationList section */
|
||||
@ -331,6 +491,15 @@
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
29CE20101B7256660057FBA3 /* Build configuration list for PBXNativeTarget "api_test" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
29CE200E1B7256660057FBA3 /* Debug */,
|
||||
29CE200F1B7256660057FBA3 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
/* End XCConfigurationList section */
|
||||
};
|
||||
rootObject = 29AB1EFE1816E3AD004B501E /* Project object */;
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
#!/usr/bin/env python
|
||||
# coding: utf-8
|
||||
|
||||
import glob
|
||||
import os.path
|
||||
@ -6,7 +7,7 @@ import re
|
||||
|
||||
PATTERN = re.compile(r'LibSource =\n("(.|[\n])*?);')
|
||||
|
||||
def copy_builtin(filename):
|
||||
def copy_builtin(filename, out_prefix):
|
||||
name = os.path.basename(filename)
|
||||
name = name.split('.')[0]
|
||||
|
||||
@ -26,16 +27,19 @@ def copy_builtin(filename):
|
||||
|
||||
constant = "LibSource =\n" + wren_source + ";"
|
||||
|
||||
with open("src/vm/wren_" + name + ".c", "r") as f:
|
||||
with open(out_prefix + name + ".c", "r") as f:
|
||||
c_source = f.read()
|
||||
|
||||
c_source = PATTERN.sub(constant, c_source)
|
||||
|
||||
with open("src/vm/wren_" + name + ".c", "w") as f:
|
||||
with open(out_prefix + name + ".c", "w") as f:
|
||||
f.write(c_source)
|
||||
|
||||
print(name)
|
||||
print(filename.ljust(25) + " → " + out_prefix + name + ".c")
|
||||
|
||||
|
||||
for f in glob.iglob("builtin/*.wren"):
|
||||
copy_builtin(f)
|
||||
copy_builtin(f, "src/vm/wren_")
|
||||
|
||||
for f in glob.iglob("src/module/*.wren"):
|
||||
copy_builtin(f, "src/module/")
|
||||
|
||||
@ -20,9 +20,14 @@
|
||||
|
||||
# Files.
|
||||
CLI_HEADERS := $(wildcard src/cli/*.h)
|
||||
VM_HEADERS := $(wildcard src/vm/*.h)
|
||||
CLI_SOURCES := $(wildcard src/cli/*.c)
|
||||
|
||||
MODULE_HEADERS := $(wildcard src/module/*.h)
|
||||
MODULE_SOURCES := $(wildcard src/module/*.c)
|
||||
|
||||
VM_HEADERS := $(wildcard src/vm/*.h)
|
||||
VM_SOURCES := $(wildcard src/vm/*.c)
|
||||
|
||||
TEST_SOURCES := $(shell find test/api -name '*.c')
|
||||
BUILD_DIR := build
|
||||
|
||||
@ -94,11 +99,13 @@ endif
|
||||
|
||||
CFLAGS := $(C_OPTIONS) $(C_WARNINGS)
|
||||
|
||||
CLI_OBJECTS := $(addprefix $(BUILD_DIR)/cli/, $(notdir $(CLI_SOURCES:.c=.o)))
|
||||
VM_OBJECTS := $(addprefix $(BUILD_DIR)/vm/, $(notdir $(VM_SOURCES:.c=.o)))
|
||||
TEST_OBJECTS := $(patsubst test/api/%.c, $(BUILD_DIR)/test/%.o, $(TEST_SOURCES))
|
||||
CLI_OBJECTS := $(addprefix $(BUILD_DIR)/cli/, $(notdir $(CLI_SOURCES:.c=.o)))
|
||||
MODULE_OBJECTS := $(addprefix $(BUILD_DIR)/module/, $(notdir $(MODULE_SOURCES:.c=.o)))
|
||||
VM_OBJECTS := $(addprefix $(BUILD_DIR)/vm/, $(notdir $(VM_SOURCES:.c=.o)))
|
||||
TEST_OBJECTS := $(patsubst test/api/%.c, $(BUILD_DIR)/test/%.o, $(TEST_SOURCES))
|
||||
|
||||
LIB_UV_DIR := build/libuv
|
||||
LIBUV_DIR := build/libuv
|
||||
LIBUV := $(LIBUV_DIR)/build/Release/libuv.a
|
||||
|
||||
# Targets ---------------------------------------------------------------------
|
||||
|
||||
@ -115,10 +122,10 @@ cli: bin/$(WREN)
|
||||
test: $(BUILD_DIR)/test/$(WREN)
|
||||
|
||||
# Command-line interpreter.
|
||||
bin/$(WREN): $(CLI_OBJECTS) $(VM_OBJECTS) $(LIB_UV_DIR)/build/Release/libuv.a
|
||||
bin/$(WREN): $(CLI_OBJECTS) $(MODULE_OBJECTS) $(VM_OBJECTS) $(LIBUV)
|
||||
@printf "%10s %-30s %s\n" $(CC) $@ "$(C_OPTIONS)"
|
||||
@mkdir -p bin
|
||||
@$(CC) $(CFLAGS) -L$(LIB_UV_DIR)/build/Release -l uv -o $@ $^ -lm
|
||||
@$(CC) $(CFLAGS) -L$(LIBUV_DIR)/build/Release -l uv -o $@ $^ -lm
|
||||
|
||||
# Static library.
|
||||
lib/lib$(WREN).a: $(VM_OBJECTS)
|
||||
@ -133,16 +140,23 @@ lib/lib$(WREN).$(SHARED_EXT): $(VM_OBJECTS)
|
||||
@$(CC) $(CFLAGS) -shared $(SHARED_LIB_FLAGS) -o $@ $^
|
||||
|
||||
# Test executable.
|
||||
$(BUILD_DIR)/test/$(WREN): $(TEST_OBJECTS) $(VM_OBJECTS) $(BUILD_DIR)/cli/io.o $(BUILD_DIR)/cli/vm.o
|
||||
$(BUILD_DIR)/test/$(WREN): $(TEST_OBJECTS) $(MODULE_OBJECTS) $(VM_OBJECTS) \
|
||||
$(BUILD_DIR)/cli/io.o $(BUILD_DIR)/cli/vm.o $(LIBUV)
|
||||
@printf "%10s %-30s %s\n" $(CC) $@ "$(C_OPTIONS)"
|
||||
@mkdir -p $(BUILD_DIR)/test
|
||||
@$(CC) $(CFLAGS) -o $@ $^ -lm
|
||||
@$(CC) $(CFLAGS) -L$(LIBUV_DIR)/build/Release -l uv -o $@ $^ -lm
|
||||
|
||||
# CLI object files.
|
||||
$(BUILD_DIR)/cli/%.o: src/cli/%.c $(CLI_HEADERS) $(VM_HEADERS)
|
||||
$(BUILD_DIR)/cli/%.o: src/cli/%.c $(CLI_HEADERS) $(MODULE_HEADERS) $(VM_HEADERS)
|
||||
@printf "%10s %-30s %s\n" $(CC) $< "$(C_OPTIONS)"
|
||||
@mkdir -p $(BUILD_DIR)/cli
|
||||
@$(CC) -c $(CFLAGS) -Isrc/include -I$(LIB_UV_DIR)/include -o $@ $(FILE_FLAG) $<
|
||||
@$(CC) -c $(CFLAGS) -Isrc/include -Isrc/module -I$(LIBUV_DIR)/include -o $@ $(FILE_FLAG) $<
|
||||
|
||||
# Module object files.
|
||||
$(BUILD_DIR)/module/%.o: src/module/%.c $(CLI_HEADERS) $(MODULE_HEADERS) $(VM_HEADERS)
|
||||
@printf "%10s %-30s %s\n" $(CC) $< "$(C_OPTIONS)"
|
||||
@mkdir -p $(BUILD_DIR)/module
|
||||
@$(CC) -c $(CFLAGS) -Isrc/include -Isrc/cli -I$(LIBUV_DIR)/include -o $@ $(FILE_FLAG) $<
|
||||
|
||||
# VM object files.
|
||||
$(BUILD_DIR)/vm/%.o: src/vm/%.c $(VM_HEADERS)
|
||||
@ -151,9 +165,9 @@ $(BUILD_DIR)/vm/%.o: src/vm/%.c $(VM_HEADERS)
|
||||
@$(CC) -c $(CFLAGS) -Isrc/include -o $@ $(FILE_FLAG) $<
|
||||
|
||||
# Test object files.
|
||||
$(BUILD_DIR)/test/%.o: test/api/%.c $(VM_HEADERS)
|
||||
$(BUILD_DIR)/test/%.o: test/api/%.c $(MODULE_HEADERS) $(VM_HEADERS)
|
||||
@printf "%10s %-30s %s\n" $(CC) $< "$(C_OPTIONS)"
|
||||
@mkdir -p $(dir $@)
|
||||
@$(CC) -c $(CFLAGS) -Isrc/include -Isrc/cli -o $@ $(FILE_FLAG) $<
|
||||
@$(CC) -c $(CFLAGS) -Isrc/include -I$(LIBUV_DIR)/include -Isrc/cli -o $@ $(FILE_FLAG) $<
|
||||
|
||||
.PHONY: all cli test vm
|
||||
|
||||
19
src/README.md
Normal file
19
src/README.md
Normal file
@ -0,0 +1,19 @@
|
||||
This contains the Wren source code. It is organized like so:
|
||||
|
||||
* `cli`: the source code for the command line interface. This is a custom
|
||||
exectuable that embeds the VM in itself. Code here handles reading
|
||||
command-line, running the REPL, loading modules from disc, etc.
|
||||
|
||||
* `include`: the public header directory for the VM. If you are embedding the
|
||||
VM in your own application, you will add this to your include path.
|
||||
|
||||
* `module`: the source code for the built-in modules that come with the CLI.
|
||||
These modules are written in a mixture of C and Wren and generally use
|
||||
[libuv][] to implement their underlying functionality.
|
||||
|
||||
* `vm`: the source code for the Wren VM itself. Unlike code in `cli` and
|
||||
`module`, this has no dependencies on libuv. If you are embedding the VM in
|
||||
your own application from source, you will compile the files here into your
|
||||
app.
|
||||
|
||||
[libuv]: http://libuv.org/
|
||||
@ -4,6 +4,8 @@
|
||||
|
||||
#include "io.h"
|
||||
|
||||
#include "timer.h"
|
||||
|
||||
char const* rootDirectory = NULL;
|
||||
|
||||
// Reads the contents of the file at [path] and returns it as a heap allocated
|
||||
@ -71,6 +73,8 @@ char* wrenFilePath(const char* name)
|
||||
|
||||
char* readModule(WrenVM* vm, const char* module)
|
||||
{
|
||||
if (strcmp(module, "timer") == 0) return timerGetSource();
|
||||
|
||||
// First try to load the module with a ".wren" extension.
|
||||
char* modulePath = wrenFilePath(module);
|
||||
char* moduleContents = readFile(modulePath);
|
||||
|
||||
@ -5,37 +5,6 @@
|
||||
#include "vm.h"
|
||||
#include "wren.h"
|
||||
|
||||
#define MAX_LINE_LENGTH 1024 // TODO: Something less arbitrary.
|
||||
|
||||
static int runRepl()
|
||||
{
|
||||
WrenVM* vm = createVM(NULL);
|
||||
|
||||
printf("\\\\/\"-\n");
|
||||
printf(" \\_/ wren v0.0.0\n");
|
||||
|
||||
char line[MAX_LINE_LENGTH];
|
||||
|
||||
for (;;)
|
||||
{
|
||||
printf("> ");
|
||||
|
||||
if (!fgets(line, MAX_LINE_LENGTH, stdin))
|
||||
{
|
||||
printf("\n");
|
||||
break;
|
||||
}
|
||||
|
||||
// TODO: Handle failure.
|
||||
wrenInterpret(vm, "Prompt", line);
|
||||
|
||||
// TODO: Automatically print the result of expressions.
|
||||
}
|
||||
|
||||
wrenFreeVM(vm);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, const char* argv[])
|
||||
{
|
||||
if (argc < 1 || argc > 2)
|
||||
@ -43,14 +12,14 @@ int main(int argc, const char* argv[])
|
||||
fprintf(stderr, "Usage: wren [file]\n");
|
||||
return 64; // EX_USAGE.
|
||||
}
|
||||
|
||||
|
||||
if (argc == 1)
|
||||
{
|
||||
runRepl();
|
||||
}
|
||||
else if (argc == 2)
|
||||
{
|
||||
runFile(NULL, argv[1]);
|
||||
runFile(argv[1], NULL);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
109
src/cli/vm.c
109
src/cli/vm.c
@ -3,12 +3,41 @@
|
||||
|
||||
#include "io.h"
|
||||
#include "vm.h"
|
||||
#include "timer.h"
|
||||
|
||||
WrenVM* createVM(WrenBindForeignMethodFn bindForeign)
|
||||
#define MAX_LINE_LENGTH 1024 // TODO: Something less arbitrary.
|
||||
|
||||
// The single VM instance that the CLI uses.
|
||||
WrenVM* vm;
|
||||
|
||||
WrenBindForeignMethodFn externalBindForeign;
|
||||
|
||||
uv_loop_t* loop;
|
||||
|
||||
static WrenForeignMethodFn bindForeignMethod(WrenVM* vm,
|
||||
const char* module,
|
||||
const char* className,
|
||||
bool isStatic,
|
||||
const char* signature)
|
||||
{
|
||||
if (strcmp(module, "timer") == 0)
|
||||
{
|
||||
return timerBindForeign(vm, className, isStatic, signature);
|
||||
}
|
||||
|
||||
if (externalBindForeign != NULL)
|
||||
{
|
||||
return externalBindForeign(vm, module, className, isStatic, signature);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void initVM()
|
||||
{
|
||||
WrenConfiguration config;
|
||||
|
||||
config.bindForeignMethodFn = bindForeign;
|
||||
config.bindForeignMethodFn = bindForeignMethod;
|
||||
config.loadModuleFn = readModule;
|
||||
|
||||
// Since we're running in a standalone process, be generous with memory.
|
||||
@ -18,12 +47,28 @@ WrenVM* createVM(WrenBindForeignMethodFn bindForeign)
|
||||
config.reallocateFn = NULL;
|
||||
config.minHeapSize = 0;
|
||||
config.heapGrowthPercent = 0;
|
||||
|
||||
return wrenNewVM(&config);
|
||||
|
||||
vm = wrenNewVM(&config);
|
||||
|
||||
// Initialize the event loop.
|
||||
loop = (uv_loop_t*)malloc(sizeof(uv_loop_t));
|
||||
uv_loop_init(loop);
|
||||
}
|
||||
|
||||
void runFile(WrenBindForeignMethodFn bindForeign, const char* path)
|
||||
static void freeVM()
|
||||
{
|
||||
timerReleaseMethods();
|
||||
|
||||
uv_loop_close(loop);
|
||||
free(loop);
|
||||
|
||||
wrenFreeVM(vm);
|
||||
}
|
||||
|
||||
void runFile(const char* path, WrenBindForeignMethodFn bindForeign)
|
||||
{
|
||||
externalBindForeign = bindForeign;
|
||||
|
||||
// Use the directory where the file is as the root to resolve imports
|
||||
// relative to.
|
||||
char* root = NULL;
|
||||
@ -42,12 +87,18 @@ void runFile(WrenBindForeignMethodFn bindForeign, const char* path)
|
||||
fprintf(stderr, "Could not find file \"%s\".\n", path);
|
||||
exit(66);
|
||||
}
|
||||
|
||||
WrenVM* vm = createVM(bindForeign);
|
||||
|
||||
|
||||
initVM();
|
||||
|
||||
WrenInterpretResult result = wrenInterpret(vm, path, source);
|
||||
|
||||
if (result == WREN_RESULT_SUCCESS)
|
||||
{
|
||||
uv_run(loop, UV_RUN_DEFAULT);
|
||||
}
|
||||
|
||||
wrenFreeVM(vm);
|
||||
freeVM();
|
||||
|
||||
free(source);
|
||||
free(root);
|
||||
|
||||
@ -55,3 +106,43 @@ void runFile(WrenBindForeignMethodFn bindForeign, const char* path)
|
||||
if (result == WREN_RESULT_COMPILE_ERROR) exit(65); // EX_DATAERR.
|
||||
if (result == WREN_RESULT_RUNTIME_ERROR) exit(70); // EX_SOFTWARE.
|
||||
}
|
||||
|
||||
int runRepl()
|
||||
{
|
||||
initVM();
|
||||
|
||||
printf("\\\\/\"-\n");
|
||||
printf(" \\_/ wren v0.0.0\n");
|
||||
|
||||
char line[MAX_LINE_LENGTH];
|
||||
|
||||
for (;;)
|
||||
{
|
||||
printf("> ");
|
||||
|
||||
if (!fgets(line, MAX_LINE_LENGTH, stdin))
|
||||
{
|
||||
printf("\n");
|
||||
break;
|
||||
}
|
||||
|
||||
// TODO: Handle failure.
|
||||
wrenInterpret(vm, "Prompt", line);
|
||||
|
||||
// TODO: Automatically print the result of expressions.
|
||||
}
|
||||
|
||||
freeVM();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
WrenVM* getVM()
|
||||
{
|
||||
return vm;
|
||||
}
|
||||
|
||||
uv_loop_t* getLoop()
|
||||
{
|
||||
return loop;
|
||||
}
|
||||
|
||||
18
src/cli/vm.h
18
src/cli/vm.h
@ -1,14 +1,22 @@
|
||||
#ifndef vm_h
|
||||
#define vm_h
|
||||
|
||||
#include "uv.h"
|
||||
#include "wren.h"
|
||||
|
||||
// Creates a new Wren VM with the CLI's module loader and other configuration.
|
||||
WrenVM* createVM(WrenBindForeignMethodFn bindForeign);
|
||||
|
||||
// Executes the Wren script at [path] in a new VM.
|
||||
//
|
||||
// Exits if the script failed or could not be loaded.
|
||||
void runFile(WrenBindForeignMethodFn bindForeign, const char* path);
|
||||
// If [bindForeign] is not `NULL`, it will be called to register any foreign
|
||||
// methods that the CLI itself doesn't handle.
|
||||
void runFile(const char* path, WrenBindForeignMethodFn bindForeign);
|
||||
|
||||
// Runs the Wren interactive REPL.
|
||||
int runRepl();
|
||||
|
||||
// Gets the currently running VM.
|
||||
WrenVM* getVM();
|
||||
|
||||
// Gets the event loop the VM is using.
|
||||
uv_loop_t* getLoop();
|
||||
|
||||
#endif
|
||||
|
||||
81
src/module/timer.c
Normal file
81
src/module/timer.c
Normal file
@ -0,0 +1,81 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "uv.h"
|
||||
|
||||
#include "timer.h"
|
||||
#include "wren.h"
|
||||
#include "vm.h"
|
||||
|
||||
// This is generated from builtin/module/timer.wren. Do not edit here.
|
||||
static const char* timerLibSource =
|
||||
"class Timer {\n"
|
||||
" static sleep(milliseconds) {\n"
|
||||
" startTimer_(milliseconds, Fiber.current)\n"
|
||||
" Fiber.yield()\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" foreign static startTimer_(milliseconds, fiber)\n"
|
||||
"\n"
|
||||
" // Called by native code.\n"
|
||||
" static resumeTimer_(fiber) {\n"
|
||||
" fiber.run()\n"
|
||||
" }\n"
|
||||
"}\n";
|
||||
|
||||
// The Wren method to call when a timer has completed.
|
||||
static WrenMethod* resumeTimer;
|
||||
|
||||
// Called by libuv when the timer has completed.
|
||||
static void timerCallback(uv_timer_t* handle)
|
||||
{
|
||||
WrenValue* fiber = (WrenValue*)handle->data;
|
||||
free(handle);
|
||||
|
||||
// Run the fiber that was sleeping.
|
||||
wrenCall(getVM(), resumeTimer, "v", fiber);
|
||||
wrenReleaseValue(getVM(), fiber);
|
||||
}
|
||||
|
||||
static void startTimer(WrenVM* vm)
|
||||
{
|
||||
// If we haven't looked up the resume method yet, grab it now.
|
||||
if (resumeTimer == NULL)
|
||||
{
|
||||
resumeTimer = wrenGetMethod(vm, "timer", "Timer", "resumeTimer_(_)");
|
||||
}
|
||||
|
||||
int milliseconds = (int)wrenGetArgumentDouble(vm, 1);
|
||||
WrenValue* fiber = wrenGetArgumentValue(vm, 2);
|
||||
|
||||
// Store the fiber to resume when the timer completes.
|
||||
uv_timer_t* handle = (uv_timer_t*)malloc(sizeof(uv_timer_t));
|
||||
handle->data = fiber;
|
||||
|
||||
uv_timer_init(getLoop(), handle);
|
||||
uv_timer_start(handle, timerCallback, milliseconds, 0);
|
||||
}
|
||||
|
||||
char* timerGetSource()
|
||||
{
|
||||
size_t length = strlen(timerLibSource);
|
||||
char* copy = malloc(length + 1);
|
||||
strncpy(copy, timerLibSource, length);
|
||||
|
||||
return copy;
|
||||
}
|
||||
|
||||
WrenForeignMethodFn timerBindForeign(
|
||||
WrenVM* vm, const char* className, bool isStatic, const char* signature)
|
||||
{
|
||||
if (strcmp(className, "Timer") != 0) return NULL;
|
||||
|
||||
if (isStatic && strcmp(signature, "startTimer_(_,_)") == 0) return startTimer;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void timerReleaseMethods()
|
||||
{
|
||||
if (resumeTimer != NULL) wrenReleaseMethod(getVM(), resumeTimer);
|
||||
}
|
||||
14
src/module/timer.h
Normal file
14
src/module/timer.h
Normal file
@ -0,0 +1,14 @@
|
||||
#ifndef timer_h
|
||||
#define timer_h
|
||||
|
||||
#include "wren.h"
|
||||
|
||||
// TODO: Coherent naming scheme.
|
||||
char* timerGetSource();
|
||||
|
||||
WrenForeignMethodFn timerBindForeign(
|
||||
WrenVM* vm, const char* className, bool isStatic, const char* signature);
|
||||
|
||||
void timerReleaseMethods();
|
||||
|
||||
#endif
|
||||
13
src/module/timer.wren
Normal file
13
src/module/timer.wren
Normal file
@ -0,0 +1,13 @@
|
||||
class Timer {
|
||||
static sleep(milliseconds) {
|
||||
startTimer_(milliseconds, Fiber.current)
|
||||
Fiber.yield()
|
||||
}
|
||||
|
||||
foreign static startTimer_(milliseconds, fiber)
|
||||
|
||||
// Called by native code.
|
||||
static resumeTimer_(fiber) {
|
||||
fiber.run()
|
||||
}
|
||||
}
|
||||
@ -60,6 +60,6 @@ int main(int argc, const char* argv[])
|
||||
strcat(testPath, testName);
|
||||
strcat(testPath, ".wren");
|
||||
|
||||
runFile(bindForeign, testPath);
|
||||
runFile(testPath, bindForeign);
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user