Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Refactor to use new module system

  • Loading branch information...
commit 3cb44fd0c70acdbfe1f26e73edebf0d5473e2294 1 parent 723769e
@creationix creationix authored
2  deps/candor
@@ -1 +1 @@
-Subproject commit deee3b5c11b87155ade2a77e2a92f6fcc25ea64d
+Subproject commit de95e65de8a39acf1b727775648dc09447c18418
View
165 src/cio.cc
@@ -3,43 +3,124 @@
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
-#include "cio_string.h"
+
+#include <assert.h>
+#include <stdio.h>
using namespace candor;
+static Object* builtins;
+static Object* builtinCache;
+
+// Print a value to a fd
+static void printValue(FILE* fd, Value* value, bool shallow) {
+ if (value->Is<String>()) {
+ String* string = value->ToString();
+ fprintf(fd, "\033[1;32m\"\033[0;32m%.*s\033[1;32m\"\033[0m", string->Length(), string->Value());
+ return;
+ }
+ if (value->Is<Number>()) {
+ String* string = value->ToString();
+ fprintf(fd, "\033[0;34m%.*s\033[0m", string->Length(), string->Value());
+ return;
+ }
+ if (value->Is<Boolean>()) {
+ String* string = value->ToString();
+ fprintf(fd, "\033[0;33m%.*s\033[0m", string->Length(), string->Value());
+ return;
+ }
+ if (value->Is<Function>()) {
+ fprintf(fd, "\033[0;36mfunction: %p\033[0m", value);
+ return;
+ }
+
+ if (value->Is<Object>()) {
+ if (shallow) {
+ fprintf(fd, "\033[0;35mobject: %p\033[0m", value);
+ return;
+ }
+ Object* obj = value->As<Object>();
+ Array* keys = obj->Keys();
+ int64_t length = keys->Length();
+ int64_t i = 0;
+ fprintf(fd, "\033[1;37m{\033[0m ");
+ while (i < length) {
+ Value* key = keys->Get(i);
+ if (key->Is<String>()) {
+ String* string = key->ToString();
+ fprintf(fd, "%.*s", string->Length(), string->Value());
+ } else {
+ fprintf(fd, "[");
+ printValue(fd, key, true);
+ fprintf(fd, "]");
+ }
+
+ fprintf(fd, "\033[1;37m:\033[0m ");
+ printValue(fd, obj->Get(key), true);
+ if (i < length - 1) {
+ fprintf(fd, "\033[1;37m,\033[0m ");
+ }
+ i++;
+ }
+ fprintf(fd, " \033[1;37m}\033[0m");
+ return;
+ }
+
+ if (value->Is<Array>()) {
+ if (shallow) {
+ fprintf(fd, "\033[0;36marray: %p\033[0m", value);
+ return;
+ }
+ Array* array = value->As<Array>();
+ int64_t length = array->Length();
+ int64_t i = 0;
+ fprintf(fd, "[ ");
+ while (i < length) {
+ printValue(fd, array->Get(i), true);
+ if (i < length - 1) {
+ fprintf(fd, ", ");
+ }
+ i++;
+ }
+ fprintf(fd, " ]");
+ return;
+ }
+
+ if (value->Is<CData>()) {
+ fprintf(fd, "\033[0;31mcdata: %p\033[0m", value);
+ return;
+ }
+
+ if (value->Is<Nil>()) {
+ fprintf(fd, "\033[1;30mnil\033[0m");
+ return;
+ }
+
+ assert(false);
+}
+
static Value* Print(uint32_t argc, Arguments& argv) {
// Print all arguments as strings with spaces and a newline.
for (uint32_t i = 0; i < argc; i++) {
- Value* value = argv[i];
- const char* part;
- uint32_t length;
- if (value->Is<Function>()) {
- part = "[Function]";
- length = 10;
- } else if (value->Is<Object>()) {
- part = "[Object]";
- length = 8;
- } else if (value->Is<Array>()) {
- part = "[Array]";
- length = 7;
- } else if (value->Is<CData>()) {
- part = "[CData]";
- length = 7;
- } else if (value->Is<Nil>()) {
- part = "nil";
- length = 3;
- } else {
- String* string = value->ToString();
- part = string->Value();
- length = string->Length();
+ String* string = argv[i]->ToString();
+ fprintf(stdout, "%.*s", string->Length(), string->Value());
+ if (i < argc - 1) {
+ fprintf(stdout, ", ");
}
+ }
+ fprintf(stdout, "\n");
+ return Nil::New();
+}
- if (i == argc - 1) {
- printf("%.*s\n", length, part);
- } else {
- printf("%.*s ", length, part);
+static Value* PrettyPrint(uint32_t argc, Arguments& argv) {
+ // Print all arguments as strings with spaces and a newline.
+ for (uint32_t i = 0; i < argc; i++) {
+ printValue(stdout, argv[i], false);
+ if (i < argc - 1) {
+ fprintf(stdout, ", ");
}
}
+ fprintf(stdout, "\n");
return Nil::New();
}
@@ -52,8 +133,34 @@ static Value* Exit(uint32_t argc, Arguments& argv) {
return Nil::New();
}
-void cio_init(Object* global) {
+static Value* LoadBuiltin(uint32_t argc, Arguments& argv) {
+ assert(argc == 1 && argv[0]->Is<String>());
+ String* name = argv[0]->As<String>();
+ Value* cache = builtinCache->Get(name);
+ if (!cache->Is<Nil>()) {
+ return cache;
+ }
+ Value* obj = builtins->Get(name);
+ assert(obj->Is<Function>());
+ Function* setup = obj->As<Function>();
+ Value* module = setup->Call(0, NULL);
+ if (!module->Is<Nil>()) {
+ builtinCache->Set(name, module);
+ }
+ return module;
+}
+
+Object* cio_init(Object* global) {
global->Set("print", Function::New(Print));
+ global->Set("prettyPrint", Function::New(PrettyPrint));
global->Set("exit", Function::New(Exit));
- cio_string_init(global);
+ global->Set("require", Function::New(LoadBuiltin));
+ builtins = Object::New();
+ builtinCache = Object::New();
+ global->Set("builtins", builtins);
+ // Make the objects persistent
+ new Handle<Object>(builtins);
+ new Handle<Object>(builtinCache);
+
+ return builtins;
}
View
2  src/cio.h
@@ -5,6 +5,6 @@
using namespace candor;
-void cio_init(Object* global);
+Object* cio_init(Object* global);
#endif
View
6 src/cio_string.cc
@@ -68,9 +68,10 @@ static Value* readInt64(uint32_t argc, Arguments& argv) {
}
-void cio_string_init(Object* global) {
+Value* cio_string_module(uint32_t argc, Arguments& argv) {
Object* string = Object::New();
- global->Set("String", string);
+ // These match the endianess of the host.
+ // TODO: add functions using explicit endianess
string->Set("readUInt8", Function::New(readUInt8));
string->Set("readInt8", Function::New(readInt8));
string->Set("readUInt16", Function::New(readUInt16));
@@ -79,4 +80,5 @@ void cio_string_init(Object* global) {
string->Set("readInt32", Function::New(readInt32));
string->Set("readUInt64", Function::New(readUInt64));
string->Set("readInt64", Function::New(readInt64));
+ return string;
}
View
2  src/cio_string.h
@@ -4,6 +4,6 @@
#include "candor.h"
using namespace candor;
-void cio_string_init(Object* global);
+Value* cio_string_module(uint32_t argc, Arguments& argv);
#endif
View
24 src/lhttp_parser.cc
@@ -5,9 +5,11 @@
#include <string.h>
#include <stdio.h>
-http_parser_settings settings;
+using namespace candor;
using namespace candorIO;
+static http_parser_settings settings;
+
static int lhttp_on_message_begin(http_parser* parser) {
return (reinterpret_cast<HttpParser*>(parser->data))->Emit("messageBegin");
}
@@ -90,8 +92,7 @@ static Value* lhttp_parse_url(uint32_t argc, Arguments& argv) {
return url;
}
-void lhttp_parser_init(Object* global) {
-
+Value* http_parser_module(uint32_t argc, Arguments& argv) {
// Initialize the settings
settings.on_message_begin = lhttp_on_message_begin;
settings.on_url = lhttp_on_url;
@@ -101,15 +102,14 @@ void lhttp_parser_init(Object* global) {
settings.on_body = lhttp_on_body;
settings.on_message_complete = lhttp_on_message_complete;
- Object* http_parser = Object::New();
- global->Set("HttpParser", http_parser);
- http_parser->Set("parseUrl", Function::New(lhttp_parse_url));
- http_parser->Set("create", Function::New(lhttp_create));
- http_parser->Set("init", Function::New(lhttp_init));
- http_parser->Set("execute", Function::New(lhttp_execute));
- http_parser->Set("finish", Function::New(lhttp_finish));
- http_parser->Set("pause", Function::New(lhttp_pause));
-
+ Object* module = Object::New();
+ module->Set("parseUrl", Function::New(lhttp_parse_url));
+ module->Set("create", Function::New(lhttp_create));
+ module->Set("init", Function::New(lhttp_init));
+ module->Set("execute", Function::New(lhttp_execute));
+ module->Set("finish", Function::New(lhttp_finish));
+ module->Set("pause", Function::New(lhttp_pause));
+ return module;
}
View
2  src/lhttp_parser.h
@@ -23,6 +23,6 @@ namespace candorIO {
}
-void lhttp_parser_init(Object* global);
+Value* http_parser_module(uint32_t argc, Arguments& argv);
#endif
View
24 src/luv.cc
@@ -1,19 +1,21 @@
#include "luv.h"
#include "candor.h"
#include "uv.h"
-#include "luv_misc.h"
-#include "luv_timer.h"
-#include "luv_tcp.h"
-using namespace candor;
+#include <stdio.h>
-void luv_init(Object* global) {
- // Create a global args array.
- Object* uv = Object::New();
- global->Set("uv", uv);
+using namespace candor;
- luv_misc_init(uv);
- luv_timer_init(uv);
- luv_tcp_init(uv);
+static Value* luv_last_error(uint32_t argc, Arguments& argv) {
+ Object* error = Object::New();
+ uv_err_t err = uv_last_error(uv_default_loop());
+ error->Set("name", String::New(uv_err_name(err)));
+ error->Set("error", String::New(uv_strerror(err)));
+ return error;
+}
+Value* uv_base_module(uint32_t argc, Arguments& argv) {
+ Object* uv = Object::New();
+ uv->Set("lastError", Function::New(luv_last_error));
+ return uv;
}
View
2  src/luv.h
@@ -28,6 +28,6 @@ enum kTYPE {
kPROCESS = isHANDLE | isPROCESS
};
-void luv_init(Object* global);
+Value* uv_base_module(uint32_t argc, Arguments& argv);
#endif
View
16 src/luv_misc.cc
@@ -1,16 +0,0 @@
-#include "candor.h"
-#include "uv.h"
-#include "luv.h"
-#include "luv_misc.h"
-
-static Value* luv_last_error(uint32_t argc, Arguments& argv) {
- Object* error = Object::New();
- uv_err_t err = uv_last_error(uv_default_loop());
- error->Set("name", String::New(uv_err_name(err)));
- error->Set("error", String::New(uv_strerror(err)));
- return error;
-}
-
-void luv_misc_init(Object* uv) {
- uv->Set("lastError", Function::New(luv_last_error));
-}
View
9 src/luv_misc.h
@@ -1,9 +0,0 @@
-#ifndef LUV_MISC_H
-#define LUV_MISC_H
-
-#include "candor.h"
-using namespace candor;
-
-void luv_misc_init(Object* uv);
-
-#endif
View
4 src/luv_tcp.cc
@@ -118,9 +118,8 @@ static Value* luv_close(uint32_t argc, Arguments& argv) {
}
// Create the Timer object that wraps the C functions
-void luv_tcp_init(Object* uv) {
+Value* uv_tcp_module(uint32_t argc, Arguments& argv) {
Object* tcp = Object::New();
- uv->Set("Tcp", tcp);
tcp->Set("create", Function::New(luv_create_tcp));
tcp->Set("nodelay", Function::New(luv_tcp_nodelay));
@@ -140,6 +139,7 @@ void luv_tcp_init(Object* uv) {
tcp->Set("isWritable", Function::New(luv_is_writable));
tcp->Set("close", Function::New(luv_close));
+ return tcp;
}
// Implement class methods.
View
2  src/luv_tcp.h
@@ -45,6 +45,6 @@ namespace candorIO {
};
}
-void luv_tcp_init(Object* uv);
+Value* uv_tcp_module(uint32_t argc, Arguments& argv);
#endif
View
4 src/luv_timer.cc
@@ -49,9 +49,8 @@ static Value* luv_close(uint32_t argc, Arguments& argv) {
// Create the Timer object that wraps the C functions
-void luv_timer_init(Object* uv) {
+Value* uv_timer_module(uint32_t argc, Arguments& argv) {
Object* timer = Object::New();
- uv->Set("Timer", timer);
timer->Set("create", Function::New(luv_create_timer));
timer->Set("start", Function::New(luv_timer_start));
timer->Set("stop", Function::New(luv_timer_stop));
@@ -59,6 +58,7 @@ void luv_timer_init(Object* uv) {
timer->Set("getRepeat", Function::New(luv_timer_get_repeat));
timer->Set("setRepeat", Function::New(luv_timer_set_repeat));
timer->Set("close", Function::New(luv_close));
+ return timer;
}
// Implement class methods.
View
2  src/luv_timer.h
@@ -27,6 +27,6 @@ namespace candorIO {
};
}
-void luv_timer_init(Object* uv);
+Value* uv_timer_module(uint32_t argc, Arguments& argv);
#endif
View
30 src/main.cc
@@ -1,13 +1,18 @@
-#include <stdio.h>
-#include <stdlib.h>
-
+// Needed for APIs used in this file
#include "candor.h"
#include "uv.h"
+// Our own header
#include "main.h"
+// The base system
#include "cio.h"
+// Addon modules
+#include "cio_string.h"
#include "luv.h"
+#include "luv_tcp.h"
+#include "luv_timer.h"
#include "lhttp_parser.h"
+// Grab some C libraries
#include <stdio.h> // fprintf
#include <stdlib.h> // abort
#include <unistd.h> // open, lseek
@@ -58,7 +63,6 @@ int main(int argc, char** argv) {
// Load script and run
off_t size = 0;
const char* script = ReadContents(argv[1], &size);
-
Function* code = Function::New(script, size);
delete script;
@@ -70,18 +74,18 @@ int main(int argc, char** argv) {
// Create a global context
Handle<Object> global(Object::New());
+ // Inject cio module into global scope, it returns an object where we need
+ // to store all module creation functions.
+ Object* builtins = cio_init(*global);
- // Inject cio module into global scope
- cio_init(*global);
-
- // Inject uv module into global scope
- luv_init(*global);
-
- // Inject http_parser
- lhttp_parser_init(*global);
+ // Store other native modules for lazy-loading
+ builtins->Set("string", Function::New(cio_string_module));
+ builtins->Set("uv", Function::New(uv_base_module));
+ builtins->Set("timer", Function::New(uv_timer_module));
+ builtins->Set("tcp", Function::New(uv_tcp_module));
+ builtins->Set("http_parser", Function::New(http_parser_module));
code->SetContext(*global);
-
code->Call(0, NULL);
// Start the libuv event loop
View
51 test-http.can
@@ -1,54 +1,7 @@
-print = global.print
+require = global.require
-// Simple pretty printer
-dump = (value) {
- type = typeof value
- if (type == "nil") {
- return "nil"
- }
- if (type == "boolean" || type == "number") {
- return "" + value
- }
- if (type == "string") {
- return '"' + value + '"'
- }
- if (type == "object") {
- keys = keysof value
- length = sizeof keys
- i = 0
- escaped = "{ "
- while (i < length) {
- key = keys[i]
- part = dump(value[key])
- escaped = escaped + key + ": " + part
- if (i < length - 1) {
- escaped = escaped + ", "
- }
- i++
- }
- return escaped + " }"
- }
- if (type == "array") {
- length = sizeof value
- i = 0
- escaped = "[ "
- while (i < length) {
- escaped = escaped + dump(value[i])
- print(escaped)
- if (i < length - 1) {
- escaped = escaped + ", "
- }
- i++
- }
- return escaped + " ]"
- }
- return "[" + type + "]"
-}
+print = global.print
-// Quick and dirty pretty printer
-p = (label, value) {
- print(label, dump(value))
-}
throw = (err) {
print(err.name + ": " + err.error)
View
72 test-tcp.can
@@ -1,86 +1,37 @@
print = global.print
-
-// Simple pretty printer
-dump = (value) {
- type = typeof value
- if (type == "nil") {
- return "nil"
- }
- if (type == "boolean" || type == "number") {
- return "" + value
- }
- if (type == "string") {
- return '"' + value + '"'
- }
- if (type == "object") {
- keys = keysof value
- length = sizeof keys
- i = 0
- escaped = "{ "
- while (i < length) {
- key = keys[i]
- part = dump(value[key])
- escaped = escaped + key + ": " + part
- if (i < length - 1) {
- escaped = escaped + ", "
- }
- i++
- }
- return escaped + " }"
- }
- if (type == "array") {
- length = sizeof value
- i = 0
- escaped = "[ "
- while (i < length) {
- escaped = escaped + dump(value[i])
- print(escaped)
- if (i < length - 1) {
- escaped = escaped + ", "
- }
- i++
- }
- return escaped + " ]"
- }
- return "[" + type + "]"
-}
-
-// Quick and dirty pretty printer
-p = (label, value) {
- print(label, dump(value))
-}
+p = global.prettyPrint
+require = global.require
throw = (err) {
- print(err.name + ": " + err.error)
+ p(err)
global.exit()
}
// Used to emit on errors when libuv badness happens
check = (status) {
if (status) {
- throw(global.uv.lastError())
+ throw(require('uv').lastError())
}
}
-Tcp = global.uv.Tcp
+Tcp = require('tcp')
p("Tcp", Tcp)
server = Tcp.create()
check(Tcp.bind(server, "0.0.0.0", 8080))
-if (err) print(err)
onConnection = (client) {
- print("onConnection")
+ p("onConnection")
check(Tcp.readStart(client, (nread, chunk) {
if (nread == -1) {
err = global.uv.lastError()
if (err.name == "EOF") {
- print("EOF")
+ p("EOF")
Tcp.shutdown(client, () {
- print("shutdown")
+ p("shutdown")
Tcp.close(client, () {
- print("closed")
+ p("closed")
})
})
} else {
@@ -89,7 +40,7 @@ onConnection = (client) {
return
}
if (nread > 0) {
- print("Echoing", chunk)
+ p("Echoing", chunk)
Tcp.write(client, chunk)
return
}
@@ -101,4 +52,5 @@ check(Tcp.listen(server, 128, () {
client = Tcp.create()
check(Tcp.accept(server, client))
onConnection(client)
-}))
+}))
+print("TCP echo server listening on port 8080")
View
21 test-timer.can
@@ -1,28 +1,31 @@
print = global.print
-Timer = global.uv.Timer
+p = global.prettyPrint
+require = global.require
+
+Timer = require('timer')
+p("Timer", Timer)
timer = Timer.create()
timer2 = Timer.create()
Timer.start(timer, 2400, 0, () {
- print("onTimeout")
+ p("onTimeout", timer)
Timer.stop(timer2)
Timer.stop(timer)
Timer.close(timer, () {
- print("close1")
+ p("close", timer)
})
Timer.close(timer2, () {
- print("close2")
+ p("close2", timer2)
})
})
Timer.start(timer2, 333, 333, () {
- Timer = global.uv.Timer
- print("onInterval")
+ p("onInterval", timer2)
period = Timer.getRepeat(timer2)
- print("period", period)
+ p("period", period)
Timer.setRepeat(timer2, period / 1.2 + 1)
})
-print("timer", timer)
-print("timer2", timer2)
+p("timer", timer)
+p("timer2", timer2)
Please sign in to comment.
Something went wrong with that request. Please try again.