// Copyright (C) 2013 Massachusetts Institute of Technology // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License version 2, // as published by the Free Software Foundation. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. // Scratch HTML5 Player // Primitives.js // Tim Mickel, July 2011 // Provides the basic primitives for the interpreter and loads in the more // complicated primitives, e.g. MotionAndPenPrims. 'use strict'; var Primitives = function() {} Primitives.prototype.addPrimsTo = function(primTable) { // Math primitives primTable['+'] = function(b) { return interp.numarg(b, 0) + interp.numarg(b, 1); }; primTable['-'] = function(b) { return interp.numarg(b, 0) - interp.numarg(b, 1); }; primTable['*'] = function(b) { return interp.numarg(b, 0) * interp.numarg(b, 1); }; primTable['/'] = function(b) { return interp.numarg(b, 0) / interp.numarg(b, 1); }; primTable['%'] = function(b) { return interp.numarg(b, 0) % interp.numarg(b, 1); }; primTable['randomFrom:to:'] = this.primRandom; primTable['<'] = function(b) { return (interp.numarg(b, 0) < interp.numarg(b, 1)); }; primTable['='] = function(b) { return (interp.arg(b, 0) == interp.arg(b, 1)); }; primTable['>'] = function(b) { return (interp.numarg(b, 0) > interp.numarg(b, 1)); }; primTable['&'] = function(b) { return interp.boolarg(b, 0) && interp.boolarg(b, 1); }; primTable['|'] = function(b) { return interp.boolarg(b, 0) || interp.boolarg(b, 1); }; primTable['not'] = function(b) { return !interp.boolarg(b, 0); }; primTable['abs'] = function(b) { return Math.abs(interp.numarg(b, 0)); }; primTable['sqrt'] = function(b) { return Math.sqrt(interp.numarg(b, 0)); }; primTable['\\\\'] = this.primModulo; primTable['rounded'] = function(b) { return Math.round(interp.numarg(b, 0)); }; primTable['computeFunction:of:'] = this.primMathFunction; // String primitives primTable['concatenate:with:'] = function(b) { return '' + interp.arg(b, 0) + interp.arg(b, 1); }; primTable['letter:of:'] = this.primLetterOf; primTable['stringLength:'] = function(b) { return interp.arg(b, 0).length; }; new VarListPrims().addPrimsTo(primTable); new MotionAndPenPrims().addPrimsTo(primTable); new LooksPrims().addPrimsTo(primTable); new SensingPrims().addPrimsTo(primTable); new SoundPrims().addPrimsTo(primTable); } Primitives.prototype.primRandom = function(b) { var n1 = interp.numarg(b, 0); var n2 = interp.numarg(b, 1); var low = n1 <= n2 ? n1 : n2; var hi = n1 <= n2 ? n2 : n1; if (low == hi) return low; // if both low and hi are ints, truncate the result to an int if (Math.floor(low) == low && Math.floor(hi) == hi) { return low + Math.floor(Math.random() * (hi + 1 - low)); } return Math.random() * (hi - low) + low; } Primitives.prototype.primLetterOf = function(b) { var s = interp.arg(b, 1); var i = interp.numarg(b, 0) - 1; if (i < 0 || i >= s.length) return ''; return s.charAt(i); } Primitives.prototype.primModulo = function(b) { var modulus = interp.numarg(b, 1); var n = interp.numarg(b, 0) % modulus; if (n < 0) n += modulus; return n; } Primitives.prototype.primMathFunction = function(b) { var op = interp.numarg(b, 0); var n = interp.numarg(b, 1); switch(op) { case 'abs': return Math.abs(n); case 'sqrt': return Math.sqrt(n); case 'sin': return Math.sin(n * Math.PI / 180); case 'cos': return Math.cos(n * Math.PI / 180); case 'tan': return Math.tan(n * Math.PI / 180); case 'asin': return Math.asin(n) * 180 / Math.PI; case 'acos': return Math.acos(n) * 180 / Math.PI; case 'atan': return Math.atan(n) * 180 / Math.PI; case 'ln': return Math.log(n); case 'log': return Math.log(n) / Math.LN10; case 'e ^': return Math.exp(n); case '10 ^': return Math.exp(n * Math.LN10); } return 0; }