2009-07-23

JSMeta on Android

We were at Old Chicago last night with friends and one of them had an Android phone, so I asked him to try out JSMeta, and he did. It didn't quite work properly, so I set up LiveAndroid 0.2 in a VM today to see for myself...

See the screenshot below. :) Something's not right... but it's more functional than I expected. Perhaps there's a JS engine bug I could report to Google...

LiveAndroid 0.2 network eth0 in VMWare Workstation

To enable LiveAndroid 0.2 networking in VMWare Workstation 6.5:


  1. Boot the LiveAndroid VM

  2. Hit Alt-F1 to switch to the root console.

  3. mkdir /data/misc/dhcp

  4. Stop the VM, and "Close" the VM in VMWare Workstation (or Exit VMWare Workstation)

  5. Edit your VM's .vmx file so the "ethernet0.virtualDev" line reads: ethernet0.virtualDev = "vlance"

  6. Open the .vmx file (launch the VM in VMWare)

  7. Set the VM to have at least 384MB RAM

  8. Start the VM; you're networked.

2009-07-08

new JSMeta revision - 0.3 or something?

Sorry, I was distracted from JSMeta by the .NET world for a week while I ported JSMeta to C#/Silverlight as an experiment slash proof-of-concept, which was more than sufficiently successful, btw.

Now MGraph projections are recognized, but they don't do anything yet. :) Toggleable XAML and M code output to be added tomorrow.


syntax Main
= something:any+ => id(something)[or => valuesof(other)];


Here's the full change/commitlog:

- added MGraph (projections) recognition (but they're still noops, just like the
variable/symbol assignments/bindings)
- lots of performance/responsiveness improvements, such as canceling the current
parse attempt if another key is pressed in the input or grammar window (kinda
difficult in single-threaded, async-emulated JS), and added lots of "fastfail"
error() combinators in the DynamicParser generator.
- fixed bug with required-interleave accepting only one interleave character
(oops)
- added new shortcut combinators UseFirst & UseSecond
- added smarter error location reporting for the die/error combinators
- added some more parser tests as a result of working on JSMetaSheet (online
spreadsheet workalike, don't try it though, yet. Goals: minimal computation,
maximally responsive UI.) :) The columns resize and cells edit/navigate
generally as expected, but formulas don't evaluate at the moment in most
browsers. :) Yes, as usual I spent way too long on the details of the UI.
Please, no one let me do UI development; I'm sorta (comparatively) slow at it.
- fixed an off-by-one error (wait, TWO off-by-one errors; ha) in the left-
recursion handling (finally discovered after an all-day debugging/diagnosis
session while working on JSMetaSheet. That kinda burned me out for a few
days... As someone commented, "that's part of the price of doing meta-meta-
meta-programming")

2009-07-06

JavaScripty C#, Part 1 of Some

I've spent the last week porting JSMeta and JSMetaPad to C# 3.0 on Silverlight 2.0. My approach to this has been the same as that of all my implementation designs lately: direct. To port JSMeta to C#, I literally copied and pasted the JavaScript code into Visual Studio 2010 beta 1 and set to work creating abstractions in C# to support the JavaScriptisms in JSMeta. Luckily, there weren't actually very many.

Lambda Expressions, Deeply



It took me a few days to realize I was actually creating a runtime that would support JavaScript's language features. I implemented JavaScript's scope [chain] as a Dictionary, accessed through a couple of layers of wrapper objects through indexer getters. It ends up being an invisibly-inherited "expando object", with members accessed by name. Those indexer getters treat their results differently depending on their type (whether they match one of several particular delegate type signatures).

I overloaded the indexer by arity: public Activation this [ string memberName, object [] ] { get {...} } , which allows the runtime "code" (actually lambda expressions; no strings/eval/CodeDom involved; pun intended) generator to "call" or "apply" the scope's member by passing in an array of arguments, if necessary.

Here's some code from the Context class demonstrating the mechanics... Sorry I'm not posting all of the code yet; I will at some point soon (this week).


//


More explanation later...

2009-06-23

JSMeta 0.2 available for play


module JSMeta {
language HelloWorld {
syntax Main = ((Bar('q') | Bar) Bar | Bar Bar Bar)+;
syntax Bar = 'a';
token Bar(param0) = 'b' param0 'z';
interleave Ignored = Language.Base.Whitespace | Language.Grammar.Comment;
}
}

2009-06-22

Property Inheritance (with a Constructor) in JavaScript

In JSMeta, I needed instances of a particular "class" (JavaScript doesn't have classes, per se, so what I really mean is objects initialized by a particular "constructor" Function) to "magically" (invisibly, automatically) inherit existing properies from another instance of that "class".

I created the following generic function that does just that:



function spawnOf(progenitor) {
// obtain a reference to the function
// that created the object
var Ctor = typeof(progenitor.constructor)!='undefined'
? progenitor.constructor
: getGlobal()[Object.prototype.toString.call(
progenitor).match(/^\[object\s(.*)\]$/)[1]];
// the below shouldn't ever happen
// (except on undefined or null)
if (typeof Ctor != 'function')
throw 'constructor not found';
// save the original prototype of
// the constructor function
var origProto = Ctor.prototype;
// replace the constructor function's
// prototype with the progenitor object
Ctor.prototype = progenitor;
// create a new "child" object, using the same
// constructor function as the progenitor object.
var childObject = new Ctor();
// replace the constructor function's prototype.
Ctor.prototype = origProto;
return childObject;
}

// from http://www.nczonline.net/blog/2008/04/20/get-the-javascript-global/
// by Nicholas C. Zakas
function getGlobal() {
return (function() {
return this;
}).call(null);
}


Here's an example of how to use it. It's useful in situations where you want to create a new object using a constructor function, but you also want the object to invisibly/automatically inherit its properties from its progenitor.



// for v8(.exe) or jsc(.exe) or whatever
// mozilla's js .exe are named
if (typeof(alert)=='undefined') alert=print;

function Gungan() {
this.toString = function() {
return "_|meesa Gungan|_"
};
if (this.constructor
===Gungan.prototype.constructor) {
// odd quirk here; this is never true in
// v8: (Gungan.prototype instanceof Gungan)
this.parent = Gungan.prototype;
}
}

var jarjar = new Gungan();

jarjar.iq = 100;

var jarjar_kid = spawnOf(jarjar);

alert(jarjar_kid.iq); // alerts "100"

jarjar_kid.iq = 85;

alert(jarjar.iq); // alerts "100"

alert(jarjar_kid.iq); // alerts "85"

alert(jarjar_kid.parent.iq); // alerts "100"

2009-06-16

How to toggle off and on the HTTP or SOCKS proxy quickly on Windows

Here's a handy script I use to quickly (one click) enable/disable the proxy for IE, Safari, and Chrome on Windows (works on vista x64 for me); sorry, I don't remember where I found the original that I modified... I just saved it in a .vbs file and made a shortcut to the .vbs file on my Quick Launch bar.


Const HKCU=&H80000001 'HKEY_CURRENT_USER
Const HKLM=&H80000002 'HKEY_LOCAL_MACHINE

Const REG_SZ=1
Const REG_EXPAND_SZ=2
Const REG_BINARY=3
Const REG_DWORD=4
Const REG_MULTI_SZ=7

Const HKCU_IE_PROXY = "Software\Microsoft\Windows\CurrentVersion\Internet Settings"

Set oReg=GetObject("winmgmts:!root/default:StdRegProv")

Main

Sub Main()

' If Proxy is set then turn it off
If GetValue(HKCU,HKCU_IE_PROXY,"ProxyEnable",REG_DWORD) = 1 Then
CreateValue HKCU,HKCU_IE_PROXY,"ProxyEnable",0,REG_DWORD
wscript.echo "Proxy Disabled"
Else
' If Proxy is not set then turn it on
CreateValue HKCU,HKCU_IE_PROXY,"ProxyEnable",1,REG_DWORD
wscript.echo "Proxy Enabled" & vbcrlf
End If

End Sub

Function CreateValue(Key,SubKey,ValueName,Value,KeyType)
Select Case KeyType
Case REG_SZ
CreateValue = oReg.SetStringValue(Key,SubKey,ValueName,Value)
Case REG_EXPAND_SZ
CreateValue = oReg.SetExpandedStringValue(Key,SubKey,ValueName,Value)
Case REG_BINARY
CreateValue = oReg.SetBinaryValue(Key,SubKey,ValueName,Value)
Case REG_DWORD
CreateValue = oReg.SetDWORDValue(Key,SubKey,ValueName,Value)
Case REG_MULTI_SZ
CreateValue = oReg.SetMultiStringValue(Key,SubKey,ValueName,Value)
End Select
End Function

Function DeleteValue(Key, SubKey, ValueName)
DeleteValue = oReg.DeleteValue(Key,SubKey,ValueName)
End Function

Function GetValue(Key, SubKey, ValueName, KeyType)

Dim Ret

Select Case KeyType
Case REG_SZ
oReg.GetStringValue Key, SubKey, ValueName, Value
Ret = Value
Case REG_EXPAND_SZ
oReg.GetExpandedStringValue Key, SubKey, ValueName, Value
Ret = Value
Case REG_BINARY
oReg.GetBinaryValue Key, SubKey, ValueName, Value
Ret = Value
Case REG_DWORD
oReg.GetDWORDValue Key, SubKey, ValueName, Value
Ret = Value
Case REG_MULTI_SZ
oReg.GetMultiStringValue Key, SubKey, ValueName, Value
Ret = Value
End Select

GetValue = Ret
End Function

2009-06-02

JSMeta now on GoogleCode - formerly "mjs" on Codeplex

This weekend I moved my language workbench project written in ECMA-262 3rd Edition (JavaScript) from codeplex to Google Code: http://jsmeta.googlecode.com

I also renamed it to JSMeta. You can run the test suite here: JSMeta Test Suite, hosted directly out of Google Code's subversion repository.

I moved it because Codeplex' Subversion-over-http implementation unfortunately does not implement serving files with the Content-Type specified in a file's property svn:mime-type , so I couldn't host the application directly out of subversion. I filed this omission as a bug here, but perhaps I should've filed it on the "codeplex" codeplex project instead of the svnbridge codeplex project; oh well.

2009-05-31

Efficient JavaScript arguments manipulation

If you're a JavaScript aficionado, you already know about the "arguments" keyword that represents a reference to a pseudo-Array Object (but is not a proper Array Object).

But did you know that you can use Array.prototype's mutator methods on it without converting it to a proper Array (pop, push, shift, unshift, concat, indexOf (except in IE, which doesn't implement it natively))? Using the mutator methods with this technique actually don't mutate the original arguments pseudo-array, but a copy/representation of it. Conveniently, using such operations on "arguments" pseudo-Arrays is much more efficient than operating on true arrays (presumably because there's one (or more) fewer boxing operation(s) the interpreter/compiler must perform).

Browser Implementations

The first browser distinction is that Internet Explorer (IE6, IE7, IE8), Chrome 1.0-3.0, Firefox 1.0-3.5, and Opera 9-10 all report "Object" as the argument's class, but Safari 3.0-4.0 reports "Arguments". This is the only difference in Safari that I have found.

Interestingly, Chrome (and its underlying V8 JavaScript engine) keep the type of the object internally as "Arguments", but the Arguments.prototype has a .toString() method that replaces "Arguments" with "Object". See what your browser says: Object.getClass(arguments)

The object referenced by `arguments` has a prototype, but its prototype has no prototype (.__proto__ member) itself.

When I began optimizing my JavaScript deferred execution engine (that serves as the basis for my implementation of Microsoft's "M" modeling/programming language (part of the product(s) code-named "Oslo")), I learned that in order to use the arguments pseudo-Array like an Array, you have to convert it to an Array, usually using something like this:
Array.prototype.slice.call(arguments)

But since then I found a much more efficient technique that (thankfully) works in all modern browsers.

Using Array.prototype.pop and Array.prototype.unshift etc on JavaScript's "arguments"

I needed to pass (to another function) a copy of a function's arguments pseudo-Array, but with the final item stripped/popped. I ended up writing a popArgs() function that does the trick, *without converting the Arguments pseudo-Array to an Array.

Each of the Array.prototype's methods (in addition to the Array constructor itself) will actually work as expected when you invoke them with the `arguments` quasi-array as the context (or the arguments Array position in the .apply() method), like so:


function popArgs() {
[].pop.call(arguments);
return arguments;
}

function testArgsPop() {
var oldArgs = arguments;
var newArgs = popArgs.apply(null, arguments);
var oldArgsArray = Array.apply(null, oldArgs);
alert(oldArgsArray.toString());
var newArgsArray = Array.apply(null, newArgs);
alert(newArgsArray.toString());
}

testArgsPop(1,2,3);

// executing this snippet alerts "1,2,3" and then "1,2"

The popArgs routine above returns an "Arguments" object, and in order to alert() it, you have to convert it to a real Array.

The important thing to note in the above code is the Array.apply(null, arguments) invocation, which (Note: search the internet for "Array.apply" for previous work/discoveries on this technique) creates an Array from the arguments pseudo-array without using slice.

Performance Testing

I wrote up some performance comparison tests (careful to use generated arguments for each invocation to prevent unwanted (in this case) compiler optimization), and found similar results to others who have tested the performance differences between Array.apply(null, array) and Array.prototype.slice.call(array, 0).

In Firefox, IE, and Opera this is the fastest technique:

var argsToArray = (function() {
// cache the slice method in a closure
var Array_prototype_slice = Array.prototype.slice;
return function argsToArray() {
return Array_prototype_slice.call(arguments, 0);
};
})();

In Chrome (V8), using Array.apply (but not necessarily caching a reference to the Array constructor in a closure) is the fastest technique:

var arrayCreator = Array;
function argsToArray() {
// don't call argsToArray, just use arrayCreator.apply(null, arguments) directly.
return arrayCreator.apply(null, arguments);
}

In Safari (4 beta with latest nightly Webkit as of 2009-05-30), Array.apply(null, arguments) is fastest (without caching a reference to Array).

By the way, both Safari 4 and Chrome 3.0 (as of this posting) are 1 or 2 decimal orders of magnitude more efficient than IE8, Firefox 3.5, and Opera 9/10alpha at these operations.