Reorganize makefile and scripts.

This commit is contained in:
Bob Nystrom
2014-01-23 23:29:50 -08:00
parent a4162a2eb3
commit 96d728cc5d
12 changed files with 237 additions and 44 deletions

6
.gitignore vendored
View File

@ -1,6 +1,10 @@
# Output directory.
# Intermediate files directory.
build/
# Built applications.
wren
wrend
# XCode user-specific stuff.
xcuserdata/
*.xccheckout

View File

@ -1,18 +1,53 @@
# Compiler flags.
CFLAGS = -std=c99 -Wall -Werror
# TODO: Add -Wextra.
DEBUG_CFLAGS = -O0 -DDEBUG
RELEASE_CFLAGS = -Os
# Files.
SOURCES = $(wildcard src/*.c)
HEADERS = $(wildcard src/*.h)
OBJECTS = $(SOURCES:.c=.o)
DEBUG_OBJECTS = $(addprefix build/debug/, $(notdir $(OBJECTS)))
RELEASE_OBJECTS = $(addprefix build/release/, $(notdir $(OBJECTS)))
.PHONY: all clean test docs corelib
all:
gcc -Iinclude src/*.c -owren
mkdir -p build/Release
mv wren build/Release
all: release
# Debug build.
debug: prep wrend
wrend: $(DEBUG_OBJECTS)
$(CC) $(CFLAGS) $(DEBUG_CFLAGS) -Iinclude -o wrend $^
build/debug/%.o: src/%.c include/wren.h $(HEADERS)
$(CC) -c $(CFLAGS) $(DEBUG_CFLAGS) -Iinclude -o $@ $<
# Release build.
release: prep wren
wren: $(RELEASE_OBJECTS)
$(CC) $(CFLAGS) $(RELEASE_CFLAGS) -Iinclude -o wren $^
build/release/%.o: src/%.c include/wren.h $(HEADERS)
$(CC) -c $(CFLAGS) $(RELEASE_CFLAGS) -Iinclude -o $@ $<
clean:
rm -rf build
rm -rf build wren wrend
test:
@./runtests
prep:
mkdir -p build/debug build/release
# Run the tests against the debug build of Wren.
test: wrend
@./script/test.py
# Generate the Wren site.
docs:
@./make_docs
@./script/generate_docs.py --watch
# Take the contents of corelib.wren and copy them into src/wren_core.c.
corelib:
@./make_corelib
@./script/generate_corelib.py

48
benchmark/fannkuch.lua Normal file
View File

@ -0,0 +1,48 @@
-- The Computer Language Benchmarks Game
-- http://benchmarksgame.alioth.debian.org/
-- contributed by Mike Pall
local function fannkuch(n)
local p, q, s, sign, maxflips, sum = {}, {}, {}, 1, 0, 0
for i=1,n do p[i] = i; q[i] = i; s[i] = i end
repeat
-- Copy and flip.
local q1 = p[1] -- Cache 1st element.
if q1 ~= 1 then
for i=2,n do q[i] = p[i] end -- Work on a copy.
local flips = 1
repeat
local qq = q[q1]
if qq == 1 then -- ... until 1st element is 1.
sum = sum + sign*flips
if flips > maxflips then maxflips = flips end -- New maximum?
break
end
q[q1] = q1
if q1 >= 4 then
local i, j = 2, q1 - 1
repeat q[i], q[j] = q[j], q[i]; i = i + 1; j = j - 1; until i >= j
end
q1 = qq; flips = flips + 1
until false
end
-- Permute.
if sign == 1 then
p[2], p[1] = p[1], p[2]; sign = -1 -- Rotate 1<-2.
else
p[2], p[3] = p[3], p[2]; sign = 1 -- Rotate 1<-2 and 1<-2<-3.
for i=3,n do
local sx = s[i]
if sx ~= 1 then s[i] = sx-1; break end
if i == n then return sum, maxflips end -- Out of permutations.
s[i] = i
-- Rotate 1<-...<-i+1.
local t = p[1]; for j=1,i do p[j] = p[j+1] end; p[i+1] = t
end
end
until false
end
local n = 9
local sum, flips = fannkuch(n)
io.write(sum, "\nPfannkuchen(", n, ") = ", flips, "\n")

56
benchmark/fannkuch.py Normal file
View File

@ -0,0 +1,56 @@
# The Computer Language Benchmarks Game
# http://benchmarksgame.alioth.debian.org/
# contributed by Isaac Gouy
# converted to Java by Oleg Mazurov
# converted to Python by Buck Golemon
# modified by Justin Peel
def fannkuch(n):
maxFlipsCount = 0
permSign = True
checksum = 0
perm1 = list(range(n))
count = perm1[:]
rxrange = range(2, n - 1)
nm = n - 1
while 1:
k = perm1[0]
if k:
perm = perm1[:]
flipsCount = 1
kk = perm[k]
while kk:
perm[:k+1] = perm[k::-1]
flipsCount += 1
k = kk
kk = perm[kk]
if maxFlipsCount < flipsCount:
maxFlipsCount = flipsCount
checksum += flipsCount if permSign else -flipsCount
# Use incremental change to generate another permutation
if permSign:
perm1[0],perm1[1] = perm1[1],perm1[0]
permSign = False
else:
perm1[1],perm1[2] = perm1[2],perm1[1]
permSign = True
for r in rxrange:
if count[r]:
break
count[r] = r
perm0 = perm1[0]
perm1[:r+1] = perm1[1:r+2]
perm1[r+1] = perm0
else:
r = nm
if not count[r]:
print( checksum )
return maxFlipsCount
count[r] -= 1
n = 9
print(( "Pfannkuchen(%i) = %i" % (n, fannkuch(n)) ))

60
benchmark/fannkuch.rb Normal file
View File

@ -0,0 +1,60 @@
def fannkuch(n)
p = (0..n).to_a
s = p.dup
q = p.dup
sign = 1
sum = maxflips = 0
while(true)
# flip.
if (q1 = p[1]) != 1
q[0..-1] = p
flips = 1
until (qq = q[q1]) == 1
q[q1] = q1
if q1 >= 4
i, j = 2, q1 - 1
while i < j
q[i], q[j] = q[j], q[i]
i += 1
j -= 1
end
end
q1 = qq
flips += 1
end
sum += sign * flips
maxflips = flips if flips > maxflips # New maximum?
end
# Permute.
if sign == 1
# Rotate 1<-2.
p[1], p[2] = p[2], p[1]
sign = -1
else
# Rotate 1<-2 and 1<-2<-3.
p[2], p[3] = p[3], p[2]
sign = 1
i = 3
while i <= n && s[i] == 1
return [sum, maxflips] if i == n # Out of permutations.
s[i] = i
# Rotate 1<-...<-i+1.
t = p.delete_at(1)
i += 1
p.insert(i, t)
end
s[i] -= 1 if i <= n
end
end
end
n = 9
sum, flips = fannkuch(n)
printf "%d\nPfannkuchen(%d) = %d\n", sum, n, flips

View File

@ -3,10 +3,15 @@
import argparse
import math
import os
import os.path
import re
import subprocess
import sys
# Runs the tests.
WREN_DIR = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))
BENCHMARK_DIR = os.path.join(WREN_DIR, 'benchmark')
# How many times to run a given benchmark.
NUM_TRIALS = 10
@ -36,9 +41,8 @@ BENCHMARK("method_call", r"""true
false""")
LANGUAGES = [
("wren", ["../build/Release/wren"], ".wren"),
("wren", ["../wren"], ".wren"),
("lua", ["lua"], ".lua"),
# ("luajit", ["luajit"], ".lua"),
("luajit (-joff)", ["luajit", "-joff"], ".lua"),
("python", ["python"], ".py"),
("ruby", ["ruby"], ".rb")
@ -75,7 +79,7 @@ def run_trial(benchmark, language):
"""Runs one benchmark one time for one language."""
args = []
args.extend(language[1])
args.append(benchmark[0] + language[2])
args.append(os.path.join(BENCHMARK_DIR, benchmark[0] + language[2]))
out = subprocess.check_output(args, universal_newlines=True)
match = benchmark[1].match(out)
if match:
@ -91,7 +95,8 @@ def run_benchmark_language(benchmark, language):
name = "{0} - {1}".format(benchmark[0], language[0])
print "{0:30s}".format(name),
if not os.path.exists(benchmark[0] + language[2]):
if not os.path.exists(os.path.join(
BENCHMARK_DIR, benchmark[0] + language[2])):
print "No implementation for this language"
return

1
example/sokoban.wren Normal file
View File

@ -0,0 +1 @@
IO.print("Hello, world!")

View File

@ -8,29 +8,9 @@ from subprocess import Popen, PIPE
import sys
# Runs the tests.
WREN_DIR = dirname(realpath(__file__))
WREN_DIR = dirname(dirname(realpath(__file__)))
TEST_DIR = join(WREN_DIR, 'test')
if sys.platform == 'win32':
WREN_APP = join(WREN_DIR, 'Debug', 'wren.exe')
if not isfile(WREN_DIR):
WREN_APP = join(WREN_DIR, 'Release', 'wren.exe')
if not isfile(WREN_APP):
sys.exit('Cannot find wren.exe!')
elif sys.platform.startswith('linux'):
WREN_APP = join(WREN_DIR, '1', 'out', 'Debug', 'wren')
if not isfile(WREN_APP):
WREN_APP = join(WREN_DIR, '1', 'out', 'Release', 'wren')
if not isfile(WREN_APP):
sys.exit('Cannot find wren!')
elif sys.platform.startswith('darwin'):
WREN_APP = join(WREN_DIR, 'build', 'Debug', 'wren')
if not isfile(WREN_APP):
WREN_APP = join(WREN_DIR, 'build', 'Release', 'wren')
if not isfile(WREN_APP):
sys.exit('Cannot find wren!')
else:
sys.exit('System not supported!')
WREN_APP = join(WREN_DIR, 'wrend')
EXPECT_PATTERN = re.compile(r'// expect: (.*)')
EXPECT_ERROR_PATTERN = re.compile(r'// expect error')

View File

@ -9,9 +9,6 @@
// This is the source file for the standalone command line interpreter. It is
// not needed if you are embedding Wren in an application.
// TODO: Don't hardcode this.
#define MAX_LINE 1024
static void failIf(bool condition, int exitCode, const char* format, ...)
{
if (!condition) return;
@ -66,8 +63,10 @@ static int runRepl(WrenVM* vm)
for (;;)
{
printf("> ");
char line[MAX_LINE];
fgets(line, MAX_LINE, stdin);
char* line = NULL;
size_t size = 0;
getline(&line, &size, stdin);
// If stdin was closed (usually meaning the used entered Ctrl-D), exit.
if (feof(stdin))
@ -77,7 +76,10 @@ static int runRepl(WrenVM* vm)
}
// TODO: Handle failure.
wrenInterpret(vm, "(repl)", line);
wrenInterpret(vm, "Prompt", line);
free(line);
// TODO: Figure out how this should work with wren API.
/*
ObjFn* fn = compile(vm, line);

View File

@ -478,7 +478,8 @@ static bool runInterpreter(WrenVM* vm)
&&code_CLASS,
&&code_SUBCLASS,
&&code_METHOD_INSTANCE,
&&code_METHOD_STATIC
&&code_METHOD_STATIC,
&&code_END
};
#define INTERPRET_LOOP DISPATCH();
@ -1022,7 +1023,8 @@ static bool runInterpreter(WrenVM* vm)
CASE_CODE(END):
// A CODE_END should always be preceded by a CODE_RETURN. If we get here,
// the compiler generated wrong code.
ASSERT(0, "Should not execute past end of bytecode.");
UNREACHABLE();
DISPATCH();
}
ASSERT(0, "Should not reach end of interpret.");