feat: add Alexander Roper to AUTHORS and expand embedding API documentation

- Add Alexander Roper to AUTHORS file with newline fix for Starbeamrainbowlabs entry
- Replace placeholder embedding API docs with full guide covering static/dynamic linking and source inclusion
- Update codebase line count from 5,000 to 7,000 lines in README and index
- Fix relative documentation links to absolute URLs in README
- Add CSS styling for preprocessor directive syntax highlighting
- Update Xcode project file references and CopyFiles build phase UUID
- Adjust delta_blue benchmark expected value from 7032700 to 14065400
- Improve markdown header detection regex in generate_docs.py to avoid matching #include
- Refactor metrics.py to exclude curly brace lines from code line counting
- Add TEST_HEADERS dependency to test object compilation in wren.mk
- Remove NULL parameter from runFile call in main.c
- Refactor vm.c to support WrenBindForeignClassFn callback and rename externalBindForeign to bindMethodFn
- Update vm.h to remove bindForeign parameter documentation and adjust runFile signature
This commit is contained in:
Bob Nystrom
2015-08-29 06:13:56 +00:00
66 changed files with 1042 additions and 487 deletions
+87
View File
@@ -0,0 +1,87 @@
#include <stdio.h>
#include <string.h>
#include "foreign_class.h"
static void counterAllocate(WrenVM* vm)
{
double* value = (double*)wrenAllocateForeign(vm, sizeof(double));
*value = 0;
}
static void counterIncrement(WrenVM* vm)
{
double* value = (double*)wrenGetArgumentForeign(vm, 0);
double increment = wrenGetArgumentDouble(vm, 1);
*value += increment;
}
static void counterValue(WrenVM* vm)
{
double value = *(double*)wrenGetArgumentForeign(vm, 0);
wrenReturnDouble(vm, value);
}
static void pointAllocate(WrenVM* vm)
{
double* coordinates = (double*)wrenAllocateForeign(vm, sizeof(double[3]));
// This gets called by both constructors, so sniff the argument count to see
// which one was invoked.
if (wrenGetArgumentCount(vm) == 1)
{
coordinates[0] = 0.0;
coordinates[1] = 0.0;
coordinates[2] = 0.0;
}
else
{
coordinates[0] = wrenGetArgumentDouble(vm, 1);
coordinates[1] = wrenGetArgumentDouble(vm, 2);
coordinates[2] = wrenGetArgumentDouble(vm, 3);
}
}
static void pointTranslate(WrenVM* vm)
{
double* coordinates = (double*)wrenGetArgumentForeign(vm, 0);
coordinates[0] += wrenGetArgumentDouble(vm, 1);
coordinates[1] += wrenGetArgumentDouble(vm, 2);
coordinates[2] += wrenGetArgumentDouble(vm, 3);
}
static void pointToString(WrenVM* vm)
{
double* coordinates = (double*)wrenGetArgumentForeign(vm, 0);
char result[100];
sprintf(result, "(%g, %g, %g)",
coordinates[0], coordinates[1], coordinates[2]);
wrenReturnString(vm, result, (int)strlen(result));
}
WrenForeignMethodFn foreignClassBindMethod(const char* signature)
{
if (strcmp(signature, "Counter.increment(_)") == 0) return counterIncrement;
if (strcmp(signature, "Counter.value") == 0) return counterValue;
if (strcmp(signature, "Point.translate(_,_,_)") == 0) return pointTranslate;
if (strcmp(signature, "Point.toString") == 0) return pointToString;
return NULL;
}
void foreignClassBindClass(
const char* className, WrenForeignClassMethods* methods)
{
if (strcmp(className, "Counter") == 0)
{
methods->allocate = counterAllocate;
return;
}
if (strcmp(className, "Point") == 0)
{
methods->allocate = pointAllocate;
return;
}
}
+5
View File
@@ -0,0 +1,5 @@
#include "wren.h"
WrenForeignMethodFn foreignClassBindMethod(const char* signature);
void foreignClassBindClass(
const char* className, WrenForeignClassMethods* methods);
+48
View File
@@ -0,0 +1,48 @@
// Class with a default constructor.
foreign class Counter {
foreign increment(amount)
foreign value
}
var counter = Counter.new()
IO.print(counter.value) // expect: 0
counter.increment(3.1)
IO.print(counter.value) // expect: 3.1
counter.increment(1.2)
IO.print(counter.value) // expect: 4.3
// Foreign classes can inherit a class as long as it has no fields.
class PointBase {
inherited() {
IO.print("inherited method")
}
}
// Class with non-default constructor.
foreign class Point is PointBase {
construct new() {
IO.print("default")
}
construct new(x, y, z) {
IO.print(x, ", ", y, ", ", z)
}
foreign translate(x, y, z)
foreign toString
}
var p = Point.new(1, 2, 3) // expect: 1, 2, 3
IO.print(p) // expect: (1, 2, 3)
p.translate(3, 4, 5)
IO.print(p) // expect: (4, 6, 8)
p = Point.new() // expect: default
IO.print(p) // expect: (0, 0, 0)
p.inherited() // expect: inherited method
var error = Fiber.new {
class Subclass is Point {}
}.try()
IO.print(error) // expect: Class 'Subclass' cannot inherit from foreign class 'Point'.
-3
View File
@@ -1,3 +0,0 @@
#include "wren.h"
WrenForeignMethodFn getValueBindForeign(const char* signature);
+30 -15
View File
@@ -5,18 +5,23 @@
#include "vm.h"
#include "wren.h"
#include "get_value/get_value.h"
#include "return_bool/return_bool.h"
#include "return_double/return_double.h"
#include "return_null/return_null.h"
#include "foreign_class.h"
#include "returns.h"
#include "value.h"
#define REGISTER_TEST(name, camelCase) \
if (strcmp(testName, #name) == 0) return camelCase##BindForeign(fullName)
#define REGISTER_METHOD(name, camelCase) \
if (strcmp(testName, #name) == 0) return camelCase##BindMethod(fullName)
#define REGISTER_CLASS(name, camelCase) \
if (strcmp(testName, #name) == 0) \
{ \
camelCase##BindClass(className, &methods); \
}
// The name of the currently executing API test.
const char* testName;
static WrenForeignMethodFn bindForeign(
static WrenForeignMethodFn bindForeignMethod(
WrenVM* vm, const char* module, const char* className,
bool isStatic, const char* signature)
{
@@ -31,10 +36,9 @@ static WrenForeignMethodFn bindForeign(
strcat(fullName, ".");
strcat(fullName, signature);
REGISTER_TEST(get_value, getValue);
REGISTER_TEST(return_bool, returnBool);
REGISTER_TEST(return_double, returnDouble);
REGISTER_TEST(return_null, returnNull);
REGISTER_METHOD(foreign_class, foreignClass);
REGISTER_METHOD(returns, returns);
REGISTER_METHOD(value, value);
fprintf(stderr,
"Unknown foreign method '%s' for test '%s'\n", fullName, testName);
@@ -42,6 +46,18 @@ static WrenForeignMethodFn bindForeign(
return NULL;
}
static WrenForeignClassMethods bindForeignClass(
WrenVM* vm, const char* module, const char* className)
{
WrenForeignClassMethods methods = { NULL, NULL };
if (strcmp(module, "main") != 0) return methods;
REGISTER_CLASS(foreign_class, foreignClass);
return methods;
}
int main(int argc, const char* argv[])
{
if (argc != 2)
@@ -52,14 +68,13 @@ int main(int argc, const char* argv[])
testName = argv[1];
// The test script is at "test/api/<test>/<test>.wren".
// The test script is at "test/api/<test>.wren".
char testPath[256];
strcpy(testPath, "test/api/");
strcat(testPath, testName);
strcat(testPath, "/");
strcat(testPath, testName);
strcat(testPath, ".wren");
runFile(testPath, bindForeign);
setForeignCallbacks(bindForeignMethod, bindForeignClass);
runFile(testPath);
return 0;
}
-21
View File
@@ -1,21 +0,0 @@
#include <string.h>
#include "return_bool.h"
static void returnTrue(WrenVM* vm)
{
wrenReturnBool(vm, true);
}
static void returnFalse(WrenVM* vm)
{
wrenReturnBool(vm, false);
}
WrenForeignMethodFn returnBoolBindForeign(const char* signature)
{
if (strcmp(signature, "static Api.returnTrue") == 0) return returnTrue;
if (strcmp(signature, "static Api.returnFalse") == 0) return returnFalse;
return NULL;
}
-3
View File
@@ -1,3 +0,0 @@
#include "wren.h"
WrenForeignMethodFn returnBoolBindForeign(const char* signature);
-7
View File
@@ -1,7 +0,0 @@
class Api {
foreign static returnTrue
foreign static returnFalse
}
IO.print(Api.returnTrue) // expect: true
IO.print(Api.returnFalse) // expect: false
-21
View File
@@ -1,21 +0,0 @@
#include <string.h>
#include "return_double.h"
static void returnInt(WrenVM* vm)
{
wrenReturnDouble(vm, 123456);
}
static void returnFloat(WrenVM* vm)
{
wrenReturnDouble(vm, 123.456);
}
WrenForeignMethodFn returnDoubleBindForeign(const char* signature)
{
if (strcmp(signature, "static Api.returnInt") == 0) return returnInt;
if (strcmp(signature, "static Api.returnFloat") == 0) return returnFloat;
return NULL;
}
-3
View File
@@ -1,3 +0,0 @@
#include "wren.h"
WrenForeignMethodFn returnDoubleBindForeign(const char* signature);
@@ -1,7 +0,0 @@
class Api {
foreign static returnInt
foreign static returnFloat
}
IO.print(Api.returnInt) // expect: 123456
IO.print(Api.returnFloat) // expect: 123.456
-15
View File
@@ -1,15 +0,0 @@
#include <string.h>
#include "return_null.h"
static void implicitNull(WrenVM* vm)
{
// Do nothing.
}
WrenForeignMethodFn returnNullBindForeign(const char* signature)
{
if (strcmp(signature, "static Api.implicitNull") == 0) return implicitNull;
return NULL;
}
-3
View File
@@ -1,3 +0,0 @@
#include "wren.h"
WrenForeignMethodFn returnNullBindForeign(const char* signature);
-5
View File
@@ -1,5 +0,0 @@
class Api {
foreign static implicitNull
}
IO.print(Api.implicitNull == null) // expect: true
+39
View File
@@ -0,0 +1,39 @@
#include <string.h>
#include "returns.h"
static void implicitNull(WrenVM* vm)
{
// Do nothing.
}
static void returnInt(WrenVM* vm)
{
wrenReturnDouble(vm, 123456);
}
static void returnFloat(WrenVM* vm)
{
wrenReturnDouble(vm, 123.456);
}
static void returnTrue(WrenVM* vm)
{
wrenReturnBool(vm, true);
}
static void returnFalse(WrenVM* vm)
{
wrenReturnBool(vm, false);
}
WrenForeignMethodFn returnsBindMethod(const char* signature)
{
if (strcmp(signature, "static Api.implicitNull") == 0) return implicitNull;
if (strcmp(signature, "static Api.returnInt") == 0) return returnInt;
if (strcmp(signature, "static Api.returnFloat") == 0) return returnFloat;
if (strcmp(signature, "static Api.returnTrue") == 0) return returnTrue;
if (strcmp(signature, "static Api.returnFalse") == 0) return returnFalse;
return NULL;
}
+3
View File
@@ -0,0 +1,3 @@
#include "wren.h"
WrenForeignMethodFn returnsBindMethod(const char* signature);
+17
View File
@@ -0,0 +1,17 @@
class Api {
foreign static implicitNull
foreign static returnInt
foreign static returnFloat
foreign static returnTrue
foreign static returnFalse
}
IO.print(Api.implicitNull == null) // expect: true
IO.print(Api.returnInt) // expect: 123456
IO.print(Api.returnFloat) // expect: 123.456
IO.print(Api.returnTrue) // expect: true
IO.print(Api.returnFalse) // expect: false
@@ -1,6 +1,6 @@
#include <string.h>
#include "get_value.h"
#include "value.h"
static WrenValue* value;
@@ -15,7 +15,7 @@ static void getValue(WrenVM* vm)
wrenReleaseValue(vm, value);
}
WrenForeignMethodFn getValueBindForeign(const char* signature)
WrenForeignMethodFn valueBindMethod(const char* signature)
{
if (strcmp(signature, "static Api.value=(_)") == 0) return setValue;
if (strcmp(signature, "static Api.value") == 0) return getValue;
+3
View File
@@ -0,0 +1,3 @@
#include "wren.h"
WrenForeignMethodFn valueBindMethod(const char* signature);
+1 -1
View File
@@ -626,7 +626,7 @@ planner = None
def delta_blue():
global total
start = time.clock()
for i in range(20):
for i in range(40):
chain_test(100)
projection_test(100)
print(total)
+9 -20
View File
@@ -34,17 +34,6 @@
// I've kept it this way to avoid deviating too much from the original
// implementation.
// TODO: Support forward declarations of globals.
var REQUIRED = null
var STRONG_REFERRED = null
var PREFERRED = null
var STRONG_DEFAULT = null
var NORMAL = null
var WEAK_DEFAULT = null
var WEAKEST = null
var ORDERED = null
// Strengths are used to measure the relative importance of constraints.
// New strengths may be inserted in the strength hierarchy without
// disrupting current constraints. Strengths cannot be created outside
@@ -67,15 +56,15 @@ class Strength {
}
// Compile time computed constants.
REQUIRED = Strength.new(0, "required")
STRONG_REFERRED = Strength.new(1, "strongPreferred")
PREFERRED = Strength.new(2, "preferred")
STRONG_DEFAULT = Strength.new(3, "strongDefault")
NORMAL = Strength.new(4, "normal")
WEAK_DEFAULT = Strength.new(5, "weakDefault")
WEAKEST = Strength.new(6, "weakest")
var REQUIRED = Strength.new(0, "required")
var STRONG_REFERRED = Strength.new(1, "strongPreferred")
var PREFERRED = Strength.new(2, "preferred")
var STRONG_DEFAULT = Strength.new(3, "strongDefault")
var NORMAL = Strength.new(4, "normal")
var WEAK_DEFAULT = Strength.new(5, "weakDefault")
var WEAKEST = Strength.new(6, "weakest")
ORDERED = [
var ORDERED = [
WEAKEST, WEAK_DEFAULT, NORMAL, STRONG_DEFAULT, PREFERRED, STRONG_REFERRED
]
@@ -701,7 +690,7 @@ var projectionTest = Fn.new {|n|
}
var start = IO.clock
for (i in 0...20) {
for (i in 0...40) {
chainTest.call(100)
projectionTest.call(100)
}
@@ -0,0 +1,9 @@
foreign class Foo {
bar {
// Can't read a field.
IO.print(_bar) // expect error
// Or write one.
_bar = "value" // expect error
}
}
@@ -0,0 +1,7 @@
class Foo {
method() {
_field = "value"
}
}
foreign class Bar is Foo {} // expect runtime error: Foreign class 'Bar' may not inherit from a class with fields.
@@ -0,0 +1,2 @@
// Missing "class".
foreign blah A {} // expect error
@@ -1 +1 @@
class Subclass is Class {} // expect runtime error: Subclass cannot inherit from Class.
class Subclass is Class {} // expect runtime error: Class 'Subclass' cannot inherit from built-in class 'Class'.
@@ -5,4 +5,4 @@ var ClosureType
ClosureType = Fn.new { IO.print(a) }.type
}
class Subclass is ClosureType {} // expect runtime error: Subclass cannot inherit from Fn.
class Subclass is ClosureType {} // expect runtime error: Class 'Subclass' cannot inherit from built-in class 'Fn'.
@@ -1 +1 @@
class Subclass is Fiber {} // expect runtime error: Subclass cannot inherit from Fiber.
class Subclass is Fiber {} // expect runtime error: Class 'Subclass' cannot inherit from built-in class 'Fiber'.
@@ -1 +1 @@
class Subclass is Fn {} // expect runtime error: Subclass cannot inherit from Fn.
class Subclass is Fn {} // expect runtime error: Class 'Subclass' cannot inherit from built-in class 'Fn'.
@@ -1 +1 @@
class Subclass is List {} // expect runtime error: Subclass cannot inherit from List.
class Subclass is List {} // expect runtime error: Class 'Subclass' cannot inherit from built-in class 'List'.
@@ -1 +1 @@
class Subclass is Map {} // expect runtime error: Subclass cannot inherit from Map.
class Subclass is Map {} // expect runtime error: Class 'Subclass' cannot inherit from built-in class 'Map'.
@@ -1 +1 @@
class Foo is 123 {} // expect runtime error: Must inherit from a class.
class Foo is 123 {} // expect runtime error: Class 'Foo' cannot inherit from a non-class object.
@@ -1 +1 @@
class Subclass is Range {} // expect runtime error: Subclass cannot inherit from Range.
class Subclass is Range {} // expect runtime error: Class 'Subclass' cannot inherit from built-in class 'Range'.
@@ -1 +1 @@
class Subclass is String {} // expect runtime error: Subclass cannot inherit from String.
class Subclass is String {} // expect runtime error: Class 'Subclass' cannot inherit from built-in class 'String'.
@@ -22,5 +22,3 @@ bar.method(1, 2) // expect: bar
bar.method(1, 2, 3) // expect: foo
bar.method(1, 2, 3, 4) // expect: bar
bar.override // expect: bar
// TODO: Prevent extending built-in types.
-1
View File
@@ -6,5 +6,4 @@ IO.print(-0) // expect: -0
IO.print(123.456) // expect: 123.456
IO.print(-0.001) // expect: -0.001
// TODO: Scientific notation?
// TODO: Literals at and beyond numeric limits.
@@ -0,0 +1 @@
var x = 1.2e // expect error
@@ -0,0 +1 @@
var x = 1.2e3.4 // expect error
@@ -0,0 +1,9 @@
var x = 2.55e2
IO.print(x) // expect: 255
IO.print(x + 1) // expect: 256
IO.print(x == 255) // expect: true
IO.print(2.55e-2 is Num) // expect: true
IO.print(x is Num) // expect: true
IO.print(-2.55e2) // expect: -255
IO.print(-25500e-2) // expect: -255
@@ -0,0 +1 @@
var x = 1e // expect error
@@ -0,0 +1 @@
var x = 1.e // expect runtime error: Num does not implement 'e'.
@@ -0,0 +1 @@
var x = 1.2e3e4 // expect error