2012-04-26

Why do all the song lyrics I try to write end up having the syllabic meter of a limerick?

2010-05-28

Perlesque Obtains Reified Continuations

Yesterday Perlesque obtained reified continuations with semantics sortof a hybrid between setjmp/longjmp and let/cc/call/cc.  The _cc keyword is an expression that returns a reference to the currently-executing stack frame (activation record), which itself holds an instruction pointer as to its progress through the routine's instructions.

The resulting Frame, whose type derives FrameBase, can be "backtracked to" by using the syntax   goto $frame   as in the below:

my $e = sub (FrameBase $f-->int) {
  say(1);
  goto $f;
  say(2);
  return 1
};
sub callcc(Callable[:(FrameBase-->int)] $func, FrameBase $frame --> int) {
  $func($frame);
  say(3);
  return 1
};
callcc($e, _cc);
say(4);

Here, the subroutine named "callcc" takes two parameters: the first is a closure that ostensibly takes a stack frame and returns an int; the second is a stack frame.  "callcc" applies its first argument to its second argument, and then prints "3".  The closure that is stored in $e prints "1", does a "longjmp" (non-local goto) to the continuation stack-frame passed in as its argument, and then prints "2" (except say("2") is unreachable, since it immediately follows a goto statement).

The output of the above is:    1  4   since the "goto $f" statement in closure $e immediately returns control to the outermost scope, at the last point it called out from it.

Note: The semantics of these continuations are slightly different from other languages' reified continuations, in that the instruction pointer is tied to the stack frame itself, and not to the continuation of the stack frame only (since in this scheme, they're one-in-the-same).

This means that if a continuation reference is "goto'd" and then "returns" and that same continuation reference is then "goto'd" again from elsewhere (if, let's say, the continuation reference was stashed in a global variable somewhere), the routine will immediately return, and/or the behavior will be undefined, since other frames could exist on the "cactus stack" that have already returned.

Edit:  awwaiid pointed out that these are coroutines, not full-blown continuations, since they aren't cloned.  So I'm adding to FrameBase an abstract .Clone() method that will be generated by the compiler, so that a cloned continuation can be restarted from where it was originally captured (or cloned again). :)

Edit:  I finished adding .Clone() method generators to the compiler, so perlesque now truly has reified *full* continuations.

2010-05-22

Perlesque: Class Predeclarations Enable Cylical Dependencies

It took a bit of mental effort/stamina to fix the bug(s) in Perlesque's class declarations pointed out by ++pmurias, but now that I did, I can see the next step for Perlesque is to enable class predeclarations (a la the ones in Perl 6), which was another lack-of-a-feature that pmurias was [implicitly ;)] grousing about.

This is an issue because Perlesque is fully strongly/statically typed (though it has upward type-inference on untyped declarations with initializers) and because its parser does the type-checking as it parses (in the first/same pass).  A naïve implementation, yes, but accordingly one that was quick-to-implement.  It also helps enforce the try-to-prevent-unnecessary-backtracking or write-the-grammar-in-such-a-way-that-backtracking-rarely-occurs strategies that ++TimToady follows with the STanDard grammar.

Perl 6 class predeclarations are provided for a similar reason, so that a typename can be referenced before its declaration body is executed (appears in the input files(s)) and its members/properties/fields/slots/state/methods are declared.  Perlesque has a stronger requirement - a class' attributes and methods must also be predeclared, but interestingly, they can be declared gradually, so a dependency graph of two classes can be built up with multiple predeclarations of each interdependent class.  This is possible because, at parse-time, the CLR TypeBuilder objects hidden behind RunSharp's TypeGen objects support gradual typing.

The syntax for method predeclaration is similar to the Perl 6 ones - a fully type-annotated method signature and an empty routine body, perhaps with a ... ellipsis to denote "stub".  

On another note, I'm still trying to think about how best to help the bootstrapping effort.  ++sorear is feverishly working on fleshing out viv's emit_p5 (the Perl 5 emission target) so that gimme5 will no longer be needed to translate STanDard to Perl 5 (an edition of STanDard that has already been translated to Perl 5 by gimme5 will initially use viv's emit_p5 to translate its own Perl 6 original to Perl 5, and from then on, the translated-by-viv edition can be used).

After trying to understand sorear's code in viv (and TimToady's, for that matter), I'm starting to suspect I should stick to the "lower" level tasks (at the VM layer).  That is, the things that Parrot provides for Rakudo.  Following that to its logical conclusion, perhaps I should continue to flesh out Perlesque so that it provides all the same sorts of features that Parrot and NQP-RX provide.  Thoughts?

2010-05-20

Perlesque's Class Declarations Obtained Custom Constructors and Single Inheritance

Tonight I completed the "next tasks" from this mornng's post: constructors (including ones with parameters, of course) for CLR classes defined in Perlesque, and single inheritance of classes.  So the following Perlesque code is valid:

class Foo {
  has int $a;
  method new (--> Foo) {
    say("made a Foo");
  }
}
class Bar is Foo {
  has int $b;
  method Baz (--> int) {
    say("a is " ~ (self.a ~ (" and b is " ~ self.b)));
    return 1;
  }
  method new (int $a, int $b --> Bar) {
    say("made a Bar with a == " ~ ($a ~ (" and b == " ~ $b)));
    self.a = $a;
    self.b = $b; 
  }
}
my $bar = Bar.new(4, 6);
$bar.a += 7;
$bar.b *= 3;
$bar.Baz();


and the output is:
made a Foo
made a Bar with a == 4 and b == 6
a is 11 and b is 18

Next, I'm going to coordinate with sorear & pmurias on #perl6 to get a handle on Cursor/LazyMap/STD/viv, with the eventual (but hopefully soon!) goal of either extending Sprixel's grammar engine to cover all of Cursor's capabilities or manually porting Cursor to perlesque (which I guess is tractable), so that viv can emit STD's parse tree of itself to perlesque, using emit_perlesque.

Then STD is running on the CLR, and it's all downhill from there.... where by "downhill" I mean the gravity is strong enough to pull us all the way down to the bottom of the hill, but there are a few PetaNewtons of friction/obstacles the gravity will have to overcome between here and there.  But at least we'll be able to see the bottom.

Perlesque Obtained Class Declarations

Yesterday I finished a feature for which Paweł Murias (pmurias) has been clamoring: class declarations in Perlesque.  Class declarations act similarly to class declarations in Perl 6:

class Individual {
  has int $x_chrom; # attributes can't have initializers yet, but it's a \smop\
  has int $y_chrom;
  has Individual $xx_parent;
  has Individual $xy_parent;
  has string $dna;
  has int $id;

  my int $indiv_id; # just a unique tag


  # this tier of the block acts as a "static initializer"
  #  for the class, and runs at "declaration-time" (when
  #  the class block is encountered as the "interpreter"
  #  evaluates the program (from the programmer's perspective),
  #  so any lexicals declared here act as "private static fields"
  #  or "class fields" would for a Java/C# class, since they
  #  are accessible from the method blocks like a normal
  #  closure.  Named subs can also be declared here.


  method conceive(Individual $mate --> Individual) {
    my $offspring = Individual.new();
    # do a bunch of somewhat randomized stuff with $mate.dna and self.dna
    $offspring.dna = "CGGCTGTAGCTGTGTCGTGATGCACGTACGTG";
    $offspring.xx_parent = self; # The self keyword is like the "this" keyword in C#
    $offspring.xy_parent = $mate;
    $offspring.id = ($indiv_id += 1); # closure access to a "private static field"
    return $offspring;
  }
}
my $indiv = Individual.new();


Basically this enables Java/C#-style programming in Perlesque, in addition to the (functional-style subsets of) JavaScript/Perl5 enabled last week.

What's next:
  • Class derivation (a small matter of programming, actually - the declarative functionality is already available in RunSharp - it merely needs exposed in Perlesque syntax).  This would enable Perlesque programs to use things like the PrototypeChain<TKey, TValue> class I wrote in C# as a base class for a Perlesque class.  PrototypeChain is a generalized edition of the hashes-with-inheritance Prototype PMC (which I thought existed in Parrot, but which I was apparently imagining, according to #perl6 on freenode).  Such a thing would be quite useful for implementing lexical "pads" at runtime in a non-optimized Perl 6 implementation (and in fact the Perlesque compiler does use PrototypeChain to keep track of the lexical scopes).
  • Custom constructors, which should behave similarly to Perl 6 custom constructors, except these will just be declared using method new (optional paramlist) { } instead of the meta-object-y-ultra-flexible way Perl 6 uses

2010-05-11

What's Implemented in Perlesque, What's Not, and The Plan

This post lists the syntax and semantics already implemented in Perlesque, my aforementioned strongly-typed subset of Perl 6 on the CLR.
  • This bears repeating: keep in mind this is a strongly-typed subset of Perl 6; variables may not change type (note: the contents/referents of variables may have a type that is derived from the variable's type).
  • Named labels and the "goto LABEL" statement, and a label can appear *after* the goto, as well.  Control may not jump "down" into another block, though, of course.  I suspect, but I'm not certain, that Perlesque is the first implementation (of a subset of Perl 6) to support this feature, but please correct me if I'm wrong.
  • Control flow blocks: if/elsif/else, while, until, repeat/while, repeat/until, loop (C-style for loop), and the "next" ("continue") and "last" ("break") statements in all of those loops.  The semantics of next and last match neither the Perl 6 spec or the Perl 5 behavior, but they're quite close to the expected behavior.
  • Declaration of lexical variables:  my $scalar_root = initializer_expression();   The type of $scalar_root is inferred from the type of the initializer expression.  One can also declare the type explicitly:  my Tree::Walker $traverser;
  • Declaration of closures as lexical variables: same as the above, but the initializer expression is also a subroutine declaration, either named or anonymous:   my $routine = sub foo(List[int] $integers, str $name --> int) { say($integers.Count ~ (" items in " ~ $name)); return 1 };   This declares a routine that takes two parameters (a List of integers and a string) and returns an integer.  foo(List[int].new(), "hihi") may also be invoked after this statement, or in any lexical scopes enclosed by the lexical scope in which foo was declared.
  • Declaration of named subroutines: same as the above, but without assigning it to a variable.
  • Type literals.  You can use the name of a type as an expression, since on the CLR's CTS (Common Type System), there is a Type type.  This (sort of) maps from the Perl 6 notion of the name of a type representing the type object.
  • Decimal (signed) integer literals, string literals "double quote: \" <-- double quote"  'single quote: \' <-- single quote', and the common numeric operation operators and comparison operators, as well as the bitwise and logical operators (including negation).  The assignment (mutate in-place) editions of the relevant operators are also implemented.
These features enable Perlesque to be a functional programming language and an imperative programming language, similar to Perl 5 and JavaScript (and Perl 6), but strongly typed.

What's missing from Perlesque (that would make it a useful "human-writable" language)?
  • good (well, any appropriate) error messages on parse failures
  • the aforementioned expression parser, so that precedence can be inferred from an operator precedence table, so so many parentheses aren't necessary when typing the code
The Plan for Perlesque:

Recall my plan for Perlesque: an assembly language to which STD.pm6 will compile itself.  TimToady's "viv" program (written in Perl 5, originally stood for VI->V, 6 to 5, though cutely it can also be read as 5 to 4) will take the output of the STD.pm6 parser (TimToady's definitional grammar written in Perl 6), and will emit Perlesque code that is a direct translation of the Perl 6 code in STD.pm6 itself.

It will translate all expressions to trees of calls into the Cursor/Perl6 runtime (written in some combination of Perlesque and C#), and all control statements to their analogous control structures in Perlesque.  Allow me to gloss over the mountain of work it will take to enable this translation and the supporting runtime libraries, but keep in mind that nearly all of that work is also "implementing Perl 6", so it's work that must be done at some point anyway.

The Perlesque translation of STD.pm6 (let's call it STD.psq) will then be compiled by perlesque.exe to CIL (let's call it STD.psq.exe), and executed on a CLR (Mono on Linux, Mac, or Windows, or .NET on Windows, or Silverlight on many platforms in many browsers).  Tada.  Perl 6.  Larry Wall's definitional parser parsing your Perl 6 and executing it directly (after compiling each compilation unit to CIL), including all the fancy multi-stage compilation and phasers (ask on #perl6 if you don't know what these are) and the other parser-entwined features of Perl 6.

2010-05-10

JSMeta became ... CSMeta

And then some.

I took the fantastic RunSharp library (see http://runsharp.googlecode.com/), which is a runtime-code-generator compiler for the CLR (works perfectly on Mono (>= 2.6) too!), threw in a dynamic parser-generator (a generator of dynamic parsers, somewhat evolved from JSMeta, though entirely rewritten (again, for the 4th time or so)), and created a compiler-compiler framework for the CLR.

The first programming language created in the environment is ... Perlesque.  It is a simple language.  It tries to stick to the syntax of the strongly-typed subset of the Perl 6 specification.  Every variable is a scalar (dollar "sigil" in front of the name), and variables have exactly the same semantics as their C# counterparts (value vs reference, except that Perlesque implements full-blown closures for value types, unlike C#).  If you are familiar with any of the multitudinous CLR languages (especially C#), you will feel right at home in Perlesque.

Here is an example of Perlesque code: Knuth's Man or Boy litmus-test for a heap-frame runtime/language:


sub A(int $k, Callable[:(--> int)] $x1,
              Callable[:(--> int)] $x2,
              Callable[:(--> int)] $x3,
              Callable[:(--> int)] $x4,
              Callable[:(--> int)] $x5 --> int)
{
    my Callable[:(--> int)] $B;
    $B = sub (--> int)
    {
        $k -= 1;
        return A($k, $B, $x1, $x2, $x3, $x4)
    };
    if $k <= 0
    {
        return ($x4() + $x5())
    }
    return $B()
}

sub K(int $n --> Callable[:(--> int)])
{
    return sub (--> int)
    {
        return $n
    }
}

say( A(10, K(1), K(-1), K(-1), K(1), K(0) ) )


The ugly "Callable" type annotation happens to be the currently-spec'd syntax for strongly-typed closures in Perl 6.  TimToady (Larry Wall) says it might improve.

This program outputs the correct result, which for the starting value of 10 (as shown here on the last line), outputs -67.

Part of CSMeta is Sprixel, which will be my Perl 6 implementation on the CLR (both Microsoft's .NET and Novell's Mono).  The front end will be a version of TimToady's STanDard Perl 6 grammar/parser (which happens to be written in Perl 6) translated (by STD.pm6 and its sister "viv") to Perlesque code, so that the parser will run in the CLR.  It remains to be seen how the middle end will look.  The back end is, of course, Perlesque/RunSharp/CLR.

Each of the components of the project's source code is redistributable under one of several very open-source licenses, namely an MIT/X11-style license for my fork of RunSharp, an Apache-style license (the Microsoft Public License, MS-PL) for some bits borrowed from the DLR (Microsoft's Dynamic Language Runtime), and the AL2 (Artistic License 2) for all of the code I wrote.  All of these licenses are certified by the OSI (Open Source Initiative - www.opensource.org), and of course the AL2 is the most liberal of them all, since it's a meta-license (it permits redistribution under any of the other licenses approved by the OSI).

All of the CLR's standard library (and any other .dll/.exe you might write, including any that provide integration with native libraries, whether on Linux, Windows, or the Mac, are available from your source code.

To build the project for mono (you'll need at least version 2.6.3; earlier versions crash on Sprixel), svn checkout the source, and  `xbuild Sprixel.sln`.   In 7-15 seconds, you'll get a Sprixel.exe, which is the first stage of the compiler chain.  Upon every invocation, Sprixel.exe builds and emits perlesque.exe, the grammar/compiler of which is specified in Sprixel's source code, in declarative/fluent-style C#.  perlesque.exe is then given the input file or string provided to Sprixel.exe as its input, and it is compiled to asmbly_1.exe, which is the compiled representation of your program.

You can then run  the man_or_boy test  by typing    mono bin/Release/Sprixel.exe t/man_or_boy.t  .  It emits TAP-style output. 

The code that the compiler-compiler emits uses a "stackless" engine, which just means the C runtime stack is not used to represent the callframes/stack of the language.  In Sprixel's case, it uses a continuation-returning-style (to a trampoline).  If you do run the above man_or_boy test, take a look at the generated asmbly_1.exe in Reflector to see what I mean.

You might ask: "What about the gigantic performance hit due to reifying the language's stackframes?"  I would answer: that's the cost of the amazing benefit of "emulating" full-blown continuations on the CLR.  The "callframe" keyword in the Perlesque language is an expression that returns the current frame.  It would enable someone to write the equivalent of call/cc or let/cc in Perlesque, from which coroutines and iterators and other state machines can be constructed.

I recommend viewing Perlesque as a human-readable assembly language (since it's fully strongly-typed using the CTS (the CLR's Common Type System)), excellent for implementing programming languages when combined with a compiler-compiler framework such as CSMeta.

Visit csmeta.org to view the code, which is safe to read, even for employees of large software companies who fear unintentionally copying source code.  Contact me if you would like to contribute, or chat with us on IRC in #perl6 on the freenode network.

There are several major things remaining in the language before I move on to porting over the necessary bits of TimToady's parser from Perl 5 to Perlesque (or C#), on which I will implement Perl 6:
  1. An actual expression-parser (using the "precedence-climbing" algorithm - Google it) - currently you specify precedence with parentheses.  This is somewhat low on the priority list, since I am viewing Perlesque as an assembly language of sorts.
  2. Declarative classes/fields/methods in Perlesque (Perl 6 calls fields "attributes", not the same as C# attributes).  This should be finished this week.
  3. External module/DLL loading.  This can happen at parse-time, due to the way RunSharp works (thanks Stefan!).
  4. Array declaration/creation.  I haven't yet decided how to co-opt the Perl 6 syntax for this.  I probably should have mentioned above that CLR generic types are directly represented in Perlesque identically to how they're represented in C#, except with [ and ] instead of < and >.  And yes, that's implemented.

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.