Last active
August 29, 2015 13:56
-
-
Save levjj/8817834 to your computer and use it in GitHub Desktop.
Units of measure with sweet.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Some minimal class for values with units | |
// (nothing exciting going on...) | |
function Unit(name,val) { | |
this.name = name; | |
this.val = val; | |
} | |
Unit.prototype.toString = function() { | |
return this.val + " " + this.name; | |
} | |
Unit.prototype.add = function(other) { | |
if ("number" == typeof other) return new Unit(this.name, this.val + other); | |
if (other.name != this.name) throw new Error("does not work"); | |
return new Unit(this.name, this.val + other.val); | |
} | |
Unit.prototype.times = function(other) { | |
if ("number" == typeof other) return new Unit(this.name, this.val * other); | |
if (other.name != this.name) throw new Error("does not work"); | |
return new Unit(this.name, this.val * other.val); | |
} | |
Unit.prototype.lessThan = function(other) { | |
if ("number" == typeof other) return this.val < other; | |
if (other.name != this.name) throw new Error("does not work"); | |
return this.val < other.val; | |
} | |
// How to define new units | |
// You can have basic SI units or derived units. | |
macro unit { | |
rule { $name = $r:expr } => { | |
macro $name { | |
rule infix {$x:expr |} => { ($r).times($x) } | |
} | |
} | |
rule { $name } => { | |
macro $name { | |
case infix {$x:expr | $name} => { | |
var name = #{$name}; | |
var nom = name[0].token.value; | |
return withSyntax($nlit = [makeValue(nom,name)]) { | |
return #{new Unit($nlit, $x)} | |
} | |
} | |
} | |
} | |
} | |
// Adding some syntactic sugar | |
// (Using "++" so we don't lose native "+") | |
macro ++ { rule infix { $x:expr | $y:expr } => { $x.add($y) } } | |
macro << { rule infix { $x:expr | $y:expr } => { $x.lessThan($y) } } | |
// Now, let's define some units! | |
unit m; | |
unit km = 1000 m; | |
unit mile = 1609 m; | |
unit miles = 1 mile; | |
unit s; | |
unit min = 60 s; | |
unit h = 60 min; | |
unit day = 24 h; | |
// And here you can use them: | |
alert(2 miles); | |
alert(1.5 km ++ 100 m); | |
alert(2 miles << 10 km); | |
alert(1 day << 23 h ++ 70 min); | |
var todos = [30 min, 2 h, 45 min, 2.5 h, 30 min]; | |
var done = 0 min; | |
while (done << 5 h) { | |
done = done ++ todos.shift(); | |
} | |
alert("Not enough time to finish: " + todos); | |
// Hint: Paste this file into http://sweetjs.org/browser/editor.html to try it out! |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment