slight doc update

This commit is contained in:
Adam D. Ruppe 2019-11-20 08:46:34 -05:00
parent 6092bb0fbd
commit a4e60e404b
7 changed files with 152 additions and 84 deletions

View File

@ -1,16 +1,6 @@
# About # About
This is a collection of modules that I've released over the years. Most of them stand alone, or have just one or two dependencies in here, so you don't have to download this whole repo. You may find some ddoc here:http://arsdnet.net/ddoc/ or you can always ask me for help. http://dpldocs.info/ This is a collection of modules that I've released over the years. Most of them stand alone, or have just one or two dependencies in here, so you don't have to download this whole repo. Ddoc available at http://arsd-official.dpldocs.info/ and you can also email me, destructionator@gmail.com or ping me as `adam_d_ruppe` on the #d IRC channel.
# Documentation
I know I'm pretty light on this. There's some ddocs but for the most part, I kinda expect you to use it the way I do: hoping things are logical and looking
at the source to fill in the gaps.
You can always catch me on email though: destructionator@gmail.com. That's
the most reliable way to reach me.
# Basic idea # Basic idea
@ -18,29 +8,15 @@ Modules are usually independent; you don't need this whole directory
but it doesn't hurt to grab it all either. but it doesn't hurt to grab it all either.
I like to compile by just passing all the modules to the command line I like to compile by just passing all the modules to the command line
at once. For example: dmd `yourapp.d` cgi.d. That's why I don't bother at once. For example: `dmd yourapp.d cgi.d`.
with a separate arsd/ directory nor with dub packages. Passing the files
is faster to compile and easier to use!
Read more about the modules at these links (docs are still works in process): You can also use the dub subpackages. See a list here:
http://code.dlang.org/packages/arsd-official
`cgi.d` info: http://arsdnet.net/web.d/cgi.d.html Not all modules in the source are in dub subpackages. If you want to use them,
I recommend you simply copy the file into your project.
`web.d` info: http://arsdnet.net/web.d/web.d.html
# 64 Bit
Believe it or not, but I still mostly use 32 bit programs myself. I try
to keep things working on 64 bit, but don't always test it. If something
doesn't compile or work on 64 bit, email me and I'll see about fixing it.
I also tend to run a version behind bleeding-edge dmd, so sometimes things
break there too. Again, if that's a problem, just email me and I can typically
get you a fix in about an hour.
Currently included are:
# Module overview
# Web related # Web related
@ -48,13 +24,13 @@ Currently included are:
| --- | --- | | --- | --- |
| `cgi.d` | base module for making webapps in D. Supports cgi, fastcgi, scgi, and embedded_httpd via -version=xxxx | | `cgi.d` | base module for making webapps in D. Supports cgi, fastcgi, scgi, and embedded_httpd via -version=xxxx |
| `dom.d` | an xml/html DOM based on what Javascript provides in browsers | | `dom.d` | an xml/html DOM based on what Javascript provides in browsers |
| `web.d` | a fancier way to write web apps. Uses reflection to make functions accessible via url with minimal boilerplate in your code |
| `email.d` | gives read and write support for emails, sending via SMTP and reading mbox files | | `email.d` | gives read and write support for emails, sending via SMTP and reading mbox files |
| `web.d.php` | a PHP library meant to ease integration of php components with `web.d` apps. Gives (read) access to the session, and full access to your D ApiProviders. | | `html.d` | functions to manipulate HTML documents, and now css and javascript with DOM functions, nested css statements, and macros for css and js. Usually NOT needed as the bulk of the functionality is in dom.d! |
| `html.d` | functions to manipulate HTML documents, and now css and javascript with DOM functions, nested css statements, and macros for css and js. |
| `oauth.d` | Oauth 1.0 implementation with some helper functions for facebook, twitter, etc. | | `oauth.d` | Oauth 1.0 implementation with some helper functions for facebook, twitter, etc. |
| `htmltotext.d` | converts html into plain text | | `htmltotext.d` | converts html into plain text |
| `rtud.d` | a real time update helper for HTML5 EventSource. Kinda buggy. | | `web.d.php` | a PHP library meant to ease integration of php components with `web.d` apps. Gives (read) access to the session, and full access to your D ApiProviders. |
| `rtud.d` | OLD: a real time update helper for HTML5 EventSource. Kinda buggy. |
| `web.d` | OLD: a fancier way to write web apps. Uses reflection to make functions accessible via url with minimal boilerplate in your code |
# Database related # Database related
@ -67,6 +43,7 @@ Currently included are:
| `sqlite.d` | a sqlite engine for database.d | | `sqlite.d` | a sqlite engine for database.d |
| `mssql.d` | a (super crappy) mssql engine for `database.d` (uses ODBC) | | `mssql.d` | a (super crappy) mssql engine for `database.d` (uses ODBC) |
| `querygenerator.d` | a user submission for generating sql queries | | `querygenerator.d` | a user submission for generating sql queries |
| `database_generation.d` | experimental module for generating database code from D code (similar to ActiveRecord) |
# Desktop app stuff # Desktop app stuff
@ -76,12 +53,12 @@ Currently included are:
| `simpledisplay.d` | gives quick and easy access to a window for drawing and input. Also has some OpenGL capabilities. | | `simpledisplay.d` | gives quick and easy access to a window for drawing and input. Also has some OpenGL capabilities. |
| `minigui.d` | a small widgetset built on top of `simpledisplay.d` offering buttons, checkboxes, etc. Almost done! | | `minigui.d` | a small widgetset built on top of `simpledisplay.d` offering buttons, checkboxes, etc. Almost done! |
| `terminal.d` | quick and easy access to a text mode console/terminal | | `terminal.d` | quick and easy access to a text mode console/terminal |
| `htmlwidget.d` | a very small html widget, built on simpledisplay.d | | `htmlwidget.d` | OLD: a very small, 100% custom (and super incomplete) html widget, built on simpledisplay.d |
# Game stuff # Game stuff
`engine.d`, `screen.d`, `audio.d` - a quick wrapper to SDL and OpenGL I used `engine.d`, `screen.d`, `audio.d` - OLD a quick wrapper to SDL and OpenGL I used
in the pre D1 days, now updated so it compiles as both D1 and in the pre D1 days, now updated so it compiles as both D1 and
D2 (use the -d switch to dmd) D2 (use the -d switch to dmd)
@ -89,6 +66,9 @@ Requires some SDL bindings.
Eventually I'll redo it. Eventually I'll redo it.
The newer files `simpleaudio.d`, `joystick.d`, and `gamehelpers.d` are the new version but
I'm still changing it.
# Reading Common Files # Reading Common Files
@ -96,8 +76,9 @@ Eventually I'll redo it.
| --- | --- | | --- | --- |
| `bmp.d` | basic .bmp file read/write support | | `bmp.d` | basic .bmp file read/write support |
| `png.d` | provides some png read/write support | | `png.d` | provides some png read/write support |
| `jpg.d` | just reading jpg header right now | | `jpeg.d` | jpeg file reading |
| `csv.d` | gives read support to csv files | | `csv.d` | gives read support to csv files |
| `jpg.d` | OLD just reading jpg header right now |
# Cool stuff # Cool stuff
@ -112,13 +93,13 @@ Eventually I'll redo it.
| Module | Description | | Module | Description |
| --- | --- | | --- | --- |
| `stb_truetype.d` | a port of the nice little C library `stb_truetype.h` to D for drawing text without external dependencies | | `http2.d` | a lighterweight alternative to curl.d |
| `eventloop.d` | first draft of a generic event loop that can be reused by several libraries try it with `terminal.d` or `simpledisplay.d` with -version=with_eventloop. Only works on Linux right now. |
| `sha.d` | implementations of the SHA1 and SHA256 algorithms |
| `curl.d` | a small wrapper around the curl library |
| `http.d` | a lighterweight alternative to curl.d |
| `color.d` | a basic color struct and some HSL functions. Also includes really basic image classes on which `png.d`, `bmp.d`, and others depend, and now some quantization and dithering algorithms. | | `color.d` | a basic color struct and some HSL functions. Also includes really basic image classes on which `png.d`, `bmp.d`, and others depend, and now some quantization and dithering algorithms. |
| `characterencodings.d` | conversion to UTF8 of various encodings | | `characterencodings.d` | conversion to UTF8 of various encodings |
| `ttf.d` | a port of the nice little C library `stb_truetype.h` to D for drawing text without external dependencies |
| `eventloop.d` | OLD first draft of a generic event loop that can be reused by several libraries try it with `terminal.d` or `simpledisplay.d` with -version=with_eventloop. Only works on Linux right now. |
| `sha.d` | OLD implementations of the SHA1 and SHA256 algorithms |
| `curl.d` | a small wrapper around the curl library |
# Obsolete # Obsolete
@ -146,7 +127,7 @@ Things I'll add when I get the time:
### Authors: ### Authors:
Thanks go to Nick Sabalausky, Trass3r, Stanislav Blinov, and maartenvd for input and patches. Thanks go to Nick Sabalausky, Trass3r, Stanislav Blinov, ketmar, and maartenvd for input and patches.
# Newer writeup: # Newer writeup:
@ -203,4 +184,4 @@ There's a few other hidden gems in the files themselves, and so much more on my
# Special Conventions # Special Conventions
idl Starting in 2019, I will be adding version info to individual modules. idl Starting in 2020, I will be adding version info to individual modules.

10
cgi.d
View File

@ -3,6 +3,8 @@
// FIXME: cgi per-request arena allocator // FIXME: cgi per-request arena allocator
// i need to add a bunch of type templates for validations... mayne @NotNull or NotNull!
// FIXME: I might make a cgi proxy class which can change things; the underlying one is still immutable // FIXME: I might make a cgi proxy class which can change things; the underlying one is still immutable
// but the later one can edit and simplify the api. You'd have to use the subclass tho! // but the later one can edit and simplify the api. You'd have to use the subclass tho!
@ -3670,7 +3672,13 @@ void doThreadScgiConnection(CustomCgi, alias fun, long maxContentLength)(Socket
// waiting for colon for header length // waiting for colon for header length
auto idx = indexOf(cast(string) chunk, ':'); auto idx = indexOf(cast(string) chunk, ':');
if(idx == -1) { if(idx == -1) {
range.popFront(); try {
range.popFront();
} catch(Exception e) {
// it is just closed, no big deal
connection.close();
return;
}
goto more_data; goto more_data;
} }

View File

@ -3,7 +3,7 @@
"targetType": "library", "targetType": "library",
"importPaths": ["."], "importPaths": ["."],
"sourceFiles": ["package.d"], "sourceFiles": ["package.d"],
"description": "A container of various subpackages that do lots of different things. You should use one of the subpackages instead of the main package in most cases, but you can try the complete package if you get duplicated dependency issues.", "description": "Subpackage collection for web, database, terminal ui, gui, scripting, and more.",
"license":"BSL-1.0", "license":"BSL-1.0",
"dependencies": { "dependencies": {
":simpledisplay": "*", ":simpledisplay": "*",

63
http2.d
View File

@ -16,6 +16,10 @@ module arsd.http2;
import std.uri : encodeComponent; import std.uri : encodeComponent;
debug(arsd_http2_verbose) debug=arsd_http2;
debug(arsd_http2) import std.stdio : writeln;
version(without_openssl) {} version(without_openssl) {}
else { else {
version=use_openssl; version=use_openssl;
@ -77,6 +81,9 @@ HttpRequest get(string url) {
return request; return request;
} }
/**
Do not forget to call `waitForCompletion()` on the returned object!
*/
HttpRequest post(string url, string[string] req) { HttpRequest post(string url, string[string] req) {
auto client = new HttpClient(); auto client = new HttpClient();
ubyte[] bdata; ubyte[] bdata;
@ -678,7 +685,7 @@ class HttpRequest {
SocketSet writeSet; SocketSet writeSet;
void advanceConnections() { int advanceConnections() {
if(readSet is null) if(readSet is null)
readSet = new SocketSet(); readSet = new SocketSet();
if(writeSet is null) if(writeSet is null)
@ -717,29 +724,45 @@ class HttpRequest {
readSet.reset(); readSet.reset();
writeSet.reset(); writeSet.reset();
bool hadOne = false;
// active requests need to be read or written to // active requests need to be read or written to
foreach(sock, request; activeRequestOnSocket) { foreach(sock, request; activeRequestOnSocket) {
// check the other sockets just for EOF, if they close, take them out of our list, // check the other sockets just for EOF, if they close, take them out of our list,
// we'll reopen if needed upon request. // we'll reopen if needed upon request.
readSet.add(sock); readSet.add(sock);
if(request.state == State.sendingHeaders || request.state == State.sendingBody) hadOne = true;
if(request.state == State.sendingHeaders || request.state == State.sendingBody) {
writeSet.add(sock); writeSet.add(sock);
hadOne = true;
}
} }
if(!hadOne)
return 1; // automatic timeout, nothing to do
tryAgain: tryAgain:
auto selectGot = Socket.select(readSet, writeSet, null, 10.seconds /* timeout */); auto selectGot = Socket.select(readSet, writeSet, null, 10.seconds /* timeout */);
if(selectGot == 0) { /* timeout */ if(selectGot == 0) { /* timeout */
// timeout // timeout
} else if(selectGot == -1) /* interrupted */ return 1;
} else if(selectGot == -1) { /* interrupted */
/*
version(Posix) {
import core.stdc.errno;
if(errno != EINTR)
throw new Exception("select error: " ~ to!string(errno));
}
*/
goto tryAgain; goto tryAgain;
else { /* ready */ } else { /* ready */
Socket[16] inactive; Socket[16] inactive;
int inactiveCount = 0; int inactiveCount = 0;
foreach(sock, request; activeRequestOnSocket) { foreach(sock, request; activeRequestOnSocket) {
if(readSet.isSet(sock)) { if(readSet.isSet(sock)) {
keep_going: keep_going:
auto got = sock.receive(buffer); auto got = sock.receive(buffer);
debug(arsd_http2) writeln("====PACKET ",got,"=====",cast(string)buffer[0 .. got],"===/PACKET==="); debug(arsd_http2_verbose) writeln("====PACKET ",got,"=====",cast(string)buffer[0 .. got],"===/PACKET===");
if(got < 0) { if(got < 0) {
throw new Exception("receive error"); throw new Exception("receive error");
} else if(got == 0) { } else if(got == 0) {
@ -753,7 +776,7 @@ class HttpRequest {
// data available // data available
request.handleIncomingData(buffer[0 .. got]); request.handleIncomingData(buffer[0 .. got]);
if(request.state == HttpRequest.State.complete) { if(request.state == HttpRequest.State.complete || request.state == HttpRequest.State.aborted) {
inactive[inactiveCount++] = sock; inactive[inactiveCount++] = sock;
// reuse the socket for another pending request, if we can // reuse the socket for another pending request, if we can
} }
@ -776,7 +799,7 @@ class HttpRequest {
if(writeSet.isSet(sock)) { if(writeSet.isSet(sock)) {
assert(request.sendBuffer.length); assert(request.sendBuffer.length);
auto sent = sock.send(request.sendBuffer); auto sent = sock.send(request.sendBuffer);
debug(arsd_http2) writeln(cast(string) request.sendBuffer); debug(arsd_http2_verbose) writeln(cast(string) request.sendBuffer);
if(sent <= 0) if(sent <= 0)
throw new Exception("send error " ~ lastSocketError); throw new Exception("send error " ~ lastSocketError);
request.sendBuffer = request.sendBuffer[sent .. $]; request.sendBuffer = request.sendBuffer[sent .. $];
@ -791,9 +814,18 @@ class HttpRequest {
} }
// we've completed a request, are there any more pending connection? if so, send them now // we've completed a request, are there any more pending connection? if so, send them now
return 0;
} }
} }
public static void resetInternals() {
socketsPerHost = null;
activeRequestOnSocket = null;
pending = null;
}
struct HeaderReadingState { struct HeaderReadingState {
bool justSawLf; bool justSawLf;
bool justSawCr; bool justSawCr;
@ -993,7 +1025,7 @@ class HttpRequest {
bodyReadingState.contentLengthRemaining += power * val; bodyReadingState.contentLengthRemaining += power * val;
power *= 16; power *= 16;
} }
debug(arsd_http2) writeln("Chunk length: ", bodyReadingState.contentLengthRemaining); debug(arsd_http2_verbose) writeln("Chunk length: ", bodyReadingState.contentLengthRemaining);
bodyReadingState.chunkedState = 1; bodyReadingState.chunkedState = 1;
data = data[a + 1 .. $]; data = data[a + 1 .. $];
goto start_over; goto start_over;
@ -1023,7 +1055,7 @@ class HttpRequest {
responseData.content ~= newData; responseData.content ~= newData;
bodyReadingState.contentLengthRemaining -= newData.length; bodyReadingState.contentLengthRemaining -= newData.length;
debug(arsd_http2) writeln("clr: ", bodyReadingState.contentLengthRemaining, " " , a, " ", can); debug(arsd_http2_verbose) writeln("clr: ", bodyReadingState.contentLengthRemaining, " " , a, " ", can);
assert(bodyReadingState.contentLengthRemaining >= 0); assert(bodyReadingState.contentLengthRemaining >= 0);
if(bodyReadingState.contentLengthRemaining == 0) { if(bodyReadingState.contentLengthRemaining == 0) {
bodyReadingState.chunkedState = 3; bodyReadingState.chunkedState = 3;
@ -1219,12 +1251,13 @@ class HttpRequest {
} }
/// Waits for the request to finish or timeout, whichever comes furst. /// Waits for the request to finish or timeout, whichever comes first.
HttpResponse waitForCompletion() { HttpResponse waitForCompletion() {
while(state != State.aborted && state != State.complete) { while(state != State.aborted && state != State.complete) {
if(state == State.unsent) if(state == State.unsent)
send(); send();
HttpRequest.advanceConnections(); if(auto err = HttpRequest.advanceConnections())
throw new Exception("waitForCompletion got err " ~ to!string(err));
} }
return responseData; return responseData;
@ -1554,7 +1587,7 @@ version(use_openssl) {
} }
@trusted @trusted
override ptrdiff_t send(const(void)[] buf, SocketFlags flags) { override ptrdiff_t send(scope const(void)[] buf, SocketFlags flags) {
//import std.stdio;writeln(cast(string) buf); //import std.stdio;writeln(cast(string) buf);
auto retval = SSL_write(ssl, buf.ptr, cast(uint) buf.length); auto retval = SSL_write(ssl, buf.ptr, cast(uint) buf.length);
if(retval == -1) { if(retval == -1) {
@ -1567,11 +1600,11 @@ version(use_openssl) {
return retval; return retval;
} }
override ptrdiff_t send(const(void)[] buf) { override ptrdiff_t send(scope const(void)[] buf) {
return send(buf, SocketFlags.NONE); return send(buf, SocketFlags.NONE);
} }
@trusted @trusted
override ptrdiff_t receive(void[] buf, SocketFlags flags) { override ptrdiff_t receive(scope void[] buf, SocketFlags flags) {
auto retval = SSL_read(ssl, buf.ptr, cast(int)buf.length); auto retval = SSL_read(ssl, buf.ptr, cast(int)buf.length);
if(retval == -1) { if(retval == -1) {
ERR_print_errors_fp(core.stdc.stdio.stderr); ERR_print_errors_fp(core.stdc.stdio.stderr);
@ -1582,7 +1615,7 @@ version(use_openssl) {
} }
return retval; return retval;
} }
override ptrdiff_t receive(void[] buf) { override ptrdiff_t receive(scope void[] buf) {
return receive(buf, SocketFlags.NONE); return receive(buf, SocketFlags.NONE);
} }

36
jsvar.d
View File

@ -342,18 +342,18 @@ var varObject(T...)(T t) {
} }
private real stringToNumber(string s) { private double stringToNumber(string s) {
real r; double r;
try { try {
r = to!real(s); r = to!double(s);
} catch (Exception e) { } catch (Exception e) {
r = real.nan; r = double.nan;
} }
return r; return r;
} }
private bool realIsInteger(real r) { private bool doubleIsInteger(double r) {
return (r == cast(long) r); return (r == cast(long) r);
} }
@ -424,7 +424,7 @@ private var _op(alias _this, alias this2, string op, T)(T t) if(op != "~") {
_this._payload._integral = f; _this._payload._integral = f;
} else { } else {
this2._type = var.Type.Floating; this2._type = var.Type.Floating;
real f = l; double f = l;
mixin("f "~op~"= t;"); mixin("f "~op~"= t;");
_this._type = var.Type.Floating; _this._type = var.Type.Floating;
_this._payload._floating = f; _this._payload._floating = f;
@ -432,7 +432,7 @@ private var _op(alias _this, alias this2, string op, T)(T t) if(op != "~") {
return _this; return _this;
} else static if(isSomeString!T) { } else static if(isSomeString!T) {
auto rhs = stringToNumber(t); auto rhs = stringToNumber(t);
if(realIsInteger(rhs)) { if(doubleIsInteger(rhs)) {
mixin("l "~op~"= cast(long) rhs;"); mixin("l "~op~"= cast(long) rhs;");
_this._type = var.Type.Integral; _this._type = var.Type.Integral;
_this._payload._integral = l; _this._payload._integral = l;
@ -443,7 +443,7 @@ private var _op(alias _this, alias this2, string op, T)(T t) if(op != "~") {
_this._type = var.Type.Integral; _this._type = var.Type.Integral;
_this._payload._integral = f; _this._payload._integral = f;
} else { } else {
real f = l; double f = l;
mixin("f "~op~"= rhs;"); mixin("f "~op~"= rhs;");
_this._type = var.Type.Floating; _this._type = var.Type.Floating;
_this._payload._floating = f; _this._payload._floating = f;
@ -487,8 +487,8 @@ private var _op(alias _this, alias this2, string op, T)(T t) if(op != "~") {
long r = cast(long) stringToNumber(this2._payload._string); long r = cast(long) stringToNumber(this2._payload._string);
long rhs; long rhs;
} else { } else {
real r = stringToNumber(this2._payload._string); double r = stringToNumber(this2._payload._string);
real rhs; double rhs;
} }
static if(isSomeString!T) { static if(isSomeString!T) {
@ -499,7 +499,7 @@ private var _op(alias _this, alias this2, string op, T)(T t) if(op != "~") {
mixin("r " ~ op ~ "= rhs;"); mixin("r " ~ op ~ "= rhs;");
static if(is(typeof(r) == real)) { static if(is(typeof(r) == double)) {
_this._type = var.Type.Floating; _this._type = var.Type.Floating;
_this._payload._floating = r; _this._payload._floating = r;
} else static if(is(typeof(r) == long)) { } else static if(is(typeof(r) == long)) {
@ -957,9 +957,9 @@ struct var {
return T.init; return T.init;
// is it sane to translate anything else? // is it sane to translate anything else?
case Type.Function: case Type.Function:
static if(isSomeString!T) static if(isSomeString!T) {
return "<function>"; return "<function>";
else static if(isDelegate!T) { } else static if(isDelegate!T) {
// making a local copy because otherwise the delegate might refer to a struct on the stack and get corrupted later or something // making a local copy because otherwise the delegate might refer to a struct on the stack and get corrupted later or something
auto func = this._payload._function; auto func = this._payload._function;
@ -993,9 +993,9 @@ struct var {
} }
public int opCmp(T)(T t) { public int opCmp(T)(T t) {
auto f = this.get!real; auto f = this.get!double;
static if(is(T == var)) static if(is(T == var))
auto r = t.get!real; auto r = t.get!double;
else else
auto r = t; auto r = t;
return cast(int)(f - r); return cast(int)(f - r);
@ -1042,12 +1042,14 @@ struct var {
PrototypeObject _object; PrototypeObject _object;
var[] _array; var[] _array;
long _integral; long _integral;
real _floating; double _floating;
string _string; string _string;
bool _boolean; bool _boolean;
var delegate(var _this, var[] args) _function; var delegate(var _this, var[] args) _function;
} }
package VarMetadata _metadata;
public void _function(var delegate(var, var[]) f) { public void _function(var delegate(var, var[]) f) {
this._payload._function = f; this._payload._function = f;
this._type = Type.Function; this._type = Type.Function;
@ -1716,6 +1718,8 @@ template makeAscii() {
enum makeAscii = helper(); enum makeAscii = helper();
} }
package interface VarMetadata { }
// just a base class we can reference when looking for native objects // just a base class we can reference when looking for native objects
class WrappedNativeObject : PrototypeObject { class WrappedNativeObject : PrototypeObject {
TypeInfo wrappedType; TypeInfo wrappedType;

View File

@ -1,5 +1,11 @@
// http://msdn.microsoft.com/en-us/library/windows/desktop/bb775498%28v=vs.85%29.aspx // http://msdn.microsoft.com/en-us/library/windows/desktop/bb775498%28v=vs.85%29.aspx
// would be cool for a scroll bar to have marking capabilities
// kinda like vim's marks just on clicks etc and visual representation
// generically. may be cool to add an up arrow to the bottom too
//
// leave a shadow of where you last were for going back easily
// So a window needs to have a selection, and that can be represented by a type. This is manipulated by various // So a window needs to have a selection, and that can be represented by a type. This is manipulated by various
// functions like cut, copy, paste. Widgets can have a selection and that would assert teh selection ownership for // functions like cut, copy, paste. Widgets can have a selection and that would assert teh selection ownership for
// the window. // the window.

View File

@ -5,13 +5,20 @@
repl is a different set of globals repl is a different set of globals
maybe ctrl+enter to execute vs insert another line maybe ctrl+enter to execute vs insert another line
write state to file write state to file
read state from file read state from file
state consists of all variables and source to functions state consists of all variables and source to functions.
maybe need @retained for a variable that is meant to keep
its value between loads?
ddoc????
Steal Ruby's [regex, capture] maybe Steal Ruby's [regex, capture] maybe
and the => operator too and the => operator too
I kinda like the javascript foo`blargh` template literals too.
*/ */
/++ /++
A small script interpreter that builds on [arsd.jsvar] to be easily embedded inside and to have has easy A small script interpreter that builds on [arsd.jsvar] to be easily embedded inside and to have has easy
@ -983,7 +990,8 @@ class FunctionLiteralExpression : Expression {
override string toString() { override string toString() {
string s = (isMacro ? "macro" : "function") ~ " ("; string s = (isMacro ? "macro" : "function") ~ " (";
s ~= arguments.toString(); if(arguments !is null)
s ~= arguments.toString();
s ~= ") "; s ~= ") ";
s ~= functionBody.toString(); s ~= functionBody.toString();
@ -1010,6 +1018,7 @@ class FunctionLiteralExpression : Expression {
override InterpretResult interpret(PrototypeObject sc) { override InterpretResult interpret(PrototypeObject sc) {
assert(DefaultArgumentDummyObject !is null); assert(DefaultArgumentDummyObject !is null);
var v; var v;
v._metadata = new ScriptFunctionMetadata(this);
v._function = (var _this, var[] args) { v._function = (var _this, var[] args) {
auto argumentsScope = new PrototypeObject(); auto argumentsScope = new PrototypeObject();
PrototypeObject scToUse; PrototypeObject scToUse;
@ -1308,6 +1317,14 @@ class DotVarExpression : VariableExpression {
assert(0); assert(0);
} }
if(e2.identifier == "__source") {
auto val = e1.interpret(sc).value;
if(auto meta = cast(ScriptFunctionMetadata) val._metadata)
return *(new var(meta.convertToString()));
else
return *(new var(val.toJson()));
}
if(auto ve = cast(VariableExpression) e1) if(auto ve = cast(VariableExpression) e1)
return this.getVarFrom(sc, ve.getVar(sc, recurse)); return this.getVarFrom(sc, ve.getVar(sc, recurse));
else if(cast(StringLiteralExpression) e1 && e2.identifier == "interpolate") { else if(cast(StringLiteralExpression) e1 && e2.identifier == "interpolate") {
@ -1489,6 +1506,10 @@ class ForeachExpression : Expression {
Expression subject; Expression subject;
Expression loopBody; Expression loopBody;
override string toString() {
return "foreach(" ~ decl.toString() ~ "; " ~ subject.toString() ~ ") " ~ loopBody.toString();
}
override InterpretResult interpret(PrototypeObject sc) { override InterpretResult interpret(PrototypeObject sc) {
var result; var result;
@ -1621,9 +1642,9 @@ class IfExpression : Expression {
} }
override string toString() { override string toString() {
string code = "if("; string code = "if ";
code ~= condition.toString(); code ~= condition.toString();
code ~= ") "; code ~= " ";
if(ifTrue !is null) if(ifTrue !is null)
code ~= ifTrue.toString(); code ~= ifTrue.toString();
else else
@ -1788,6 +1809,10 @@ class ParentheticalExpression : Expression {
this.inside = inside; this.inside = inside;
} }
override string toString() {
return "(" ~ inside.toString() ~ ")";
}
override InterpretResult interpret(PrototypeObject sc) { override InterpretResult interpret(PrototypeObject sc) {
return InterpretResult(inside.interpret(sc).value, sc); return InterpretResult(inside.interpret(sc).value, sc);
} }
@ -2534,9 +2559,9 @@ Expression parseExpression(MyTokenStreamHere)(ref MyTokenStreamHere tokens, bool
} else } else
ret = parseAddend(tokens); ret = parseAddend(tokens);
} else { } else {
assert(0); //assert(0);
// return null; // return null;
// throw new ScriptCompileException("Parse error, unexpected end of input when reading expression", token.lineNumber); throw new ScriptCompileException("Parse error, unexpected end of input when reading expression", 0);//token.lineNumber);
} }
//writeln("parsed expression ", ret.toString()); //writeln("parsed expression ", ret.toString());
@ -2924,3 +2949,14 @@ void repl(var globals) {
} }
} }
} }
class ScriptFunctionMetadata : VarMetadata {
FunctionLiteralExpression fle;
this(FunctionLiteralExpression fle) {
this.fle = fle;
}
string convertToString() {
return fle.toString();
}
}