Git Product home page Git Product logo

puma's Introduction

PumaScript Build Status Join the chat at https://gitter.im/emravera/puma

PumaScript is a research programming language that adds meta-programming capabilities to JavaScript and is develop at the Universidad Tecnologica Nacional (UTN-FRC) in Cordoba, Argentina.

It has exactly the same syntax and semantic than regular JavaScript plus meta-programming capabilities such as introspection and re-writing features.

A number of PumaScript features are based on LayerD project. Which is a meta-programming framework for statically typed languages.

Getting started with Puma

npm install -g grunt grunt-cli

In order to set-up PumaScript environment to give a try follow these steps:

git clone https://github.com/pumascript/puma.git
npm install
grunt init

After these steps PumaScript editor is ready to start coding. Open in your browser puma's editor:

editor/puma-editor.html

The editor shows two frames side by side. The one in the left allows writing code in PumaScript language and the one in the right is used to see the results of re-writing after pressing the button "Execute".

Now is time to write the Simple PumaScript program!

Simple PumaScript Program

Any JavaScript program is a PumaScript program. Write the following snippet in the PumaScript section of the editor:

    /** @meta */
    function sum(a, b)
    {
        return pumaAst( $a +  $b);
    }
    sum(5, 6);

The sample declares the meta-function "sum" that takes two arguments. These arguments are not values but AST (Abstract Syntax Tree) of the actual arguments.

The return expression use the special function "pumaAst" to build a new AST and replace the identifiers "$a" and "$b" with the AST of the actual arguments. In the sample, "sum" is called with literals "5" and "6".

So, the expression "sum(5, 6)" will be re-written in the JavaScript panel as:

5 + 6

A more useful example of usage:

This example show how to use PumaScript metafunctions to re-write JQuery selectors into native JavaScript functions:

/* @meta */
function $(a){
    return pumaAst( jQuery(document.getElementById($a)) );
}

Will re-write:

$("#some-panel");

Into this line:

jQuery(document.getElementById('#some-panel'));

A meta-function can avoid re-writing the caller expression by returning null instead of the AST.

If you wish want more examples, you could go to PumaScript wiki.

Using PumaScript with require

PumaScript was developed as a AMD module so it can be used with any JavaScript module loader. In order to use in your project copy the src folder to your project.

To include the functionality using requireJS into your code add the following:

<script data-main="/src/pumascript.js" src="require.js"></script>

Now you can use PumaScript in your code in this way:

    var puma = require('pumascript');
    puma.evalPuma('<PUMA PROGRAM STRING HERE>');

Bugs Report

Feel free to create an issue onto Github issues tracker and add the right label. Also you can get in touch and we will do that for you.

Would do you like contribute?

We have ton of work that need to be claimed. From coding to documentation. Don't hesitate to contact. We'll waiting for you.

License

MIT. Details on LICENSE file.

puma's People

Contributors

agu-gc avatar alanpipino avatar albertinad avatar albertinadx avatar alexisferreyra avatar boehlergerman avatar chelogonzalez avatar consugus avatar emravera avatar gitter-badger avatar jalvare2 avatar kwafoawua avatar leolujan avatar marianoapp avatar nestornav avatar pemattio avatar pignatar0md avatar rhmedel avatar sidval avatar undre4m avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

puma's Issues

Clean up npm distribution package

Clean up npm distribution package to avoid uploading unnecessary files that developers don't need for using pumascript, such as: tracks, gruntfile and probably tests.

The value of a StatementList is not the value of the last value producing Statement in it.

The value of a StatementList is not the value of the last value producing Statement in the StatementList as convened on the ECMA-262 Specification:

NOTE Steps 5 and 6 of the above algoritm ensure that the value of a StatementList is the value of the last value producing Statement in the StatementList. For example, the following calls to the eval function all return the value 1: "snip"

Related tests: test/suites/Tests-12-ECMA.js: [lines 15, 21, 28]

Missing in operator

The in operator, as specified in the ECMA Standard [http://www.ecma-international.org/ecma-262/5.1/#sec-11.8.7], is not handled at runtime. E.g.:

var trees = ["redwood", "bay", "cedar", "oak", "maple"];
6 in trees;

awards you with:

[2, 0] binary operator "in" not found

Document API

Add documentation to all relevant interfaces, taking into account parameters and return types

Support for ternary conditional operators

Add support for conditional operators as defined in the ECMA Standard [http://www.ecma-international.org/ecma-262/5.1/#sec-11.12] E.g.:

false ? 'manzana' : 'naranja';

and nested conditional operators:

firstCheck ? "Access denied" : secondCheck ? "Access denied" : "Access granted";

Function.prototype.bind() method fails

Using the Function.prototype.bind() method [http://www.ecma-international.org/ecma-262/5.1/#sec-15.3.4.5] makes the process fail or doesn't return the object correctly. E.g.:

var scope = 'global';
var order = { scope: 'THIS', getScope: Function('return this.scope;') };
var unbound_scope = order.getScope;
var order_scope = unbound_scope.bind(order);
order_scope();

or

this.x = 9; 
var module = {
  x: 81,
  getX: function() { return this.x; }
};

var retrieveX = module.getX;

var boundGetX = retrieveX.bind(module);
boundGetX();

Wrong return values for Object.prototype.toString() method

The Object.prototype.toString() method, when called, should return the following:

  1. If the this value is undefined, return "[object Undefined]".
  2. If the this value is null, return "[object Null]".
    (...)
    as specified in the ECMA Standard [http://www.ecma-international.org/ecma-262/5.1/#sec-15.2.4.2]

Calling the method with the this parameter set as either undefined or null values returns [object DOMWindow] E.g.:

Object.prototype.toString.call(undefined);

Update the libraries of puma

Upgrate to latest version the libraries of esprima and escodegen.

In other hand we need to have up to date all the current libraries in the project Take special care with phantomjs lib.

Exception thrown on editor when loading and no previous save point.

When no key-value pair is stored in Local Storage, calling localStorage.getItem will resolve to null.
There's no check implemented so it's throwing an Exception when passed to Codemirror.

codemirror.js:1368 Uncaught TypeError: Cannot read property 'split' of null
at splitLinesAuto (codemirror.js:1368)
at Doc.splitLines (codemirror.js:6256)
at Doc. (codemirror.js:5906)
at Doc.setValue (codemirror.js:3879)
at CodeMirror$1.setValue (codemirror.js:9263)
at PumaEditor.setEditorValue (editor.js:68)
at PumaEditor.load (editor.js:72)

Delete parameter "Passed!" in methods ok() and equals() from all tests

From the QUnit Documentation:

https://api.qunitjs.com/equal/#equal-actual-expected-message

equal( actual, expected [, message ] )

Description: A non-strict comparison, roughly equivalent to JUnit's assertEquals.
actual - Type: Object - Expression being tested
expected - Type: Object - Known comparison value
message - Type: String - A short description of the assertion

The equal assertion uses the simple comparison operator (==) to compare the actual and expected arguments. When they are equal, the assertion passes; otherwise, it fails. When it fails, both actual and expected values are displayed in the test result, in addition to a given message.

https://api.qunitjs.com/ok/#ok-state-message

ok( state [, message ] )

Description: A boolean check, equivalent to CommonJS's assert.ok() and JUnit's assertTrue(). Passes if the first argument is truthy.
state - Type: Expression - Expression being tested
message - Type: String - A short description of the assertion

The most basic assertion in QUnit, ok() requires just one argument. If the argument evaluates to true, the assertion passes; otherwise, it fails. If a second message argument is provided, it will be displayed in place of the result.

Meaning

The message arguments are actually optional and are supposed to reflect the purpose of the test. In our case the test suite should be reviewed and for every test this last argument either be removed or modified to serve the test objective.

Postfix Increment and Decrement Operators not respecting order of return and execution

Postfix Increment Operators¹ (lhs++) and Postfix Decrement Operators² (lhs--) do not respect the order of operation execution as defined by the ECMA-262v5.1 Standard:
1 - https://www.ecma-international.org/ecma-262/5.1/#sec-11.3.1
2 - https://www.ecma-international.org/ecma-262/5.1/#sec-11.3.2

E.g.:
var i = 1; var a = [false, false]; a[i--] = 1; a;
returns a = [1, false] instead of a = [false, 1] which a correct operation should result in.

and conditional expressions that expect such behaviour could result in infinite loops. Like:

var a = [null, null]; for(var i = 0; i < a.length; a[i++] = 0); a;

Grunt task working

Make puma accesible using npm the puma module to be integrated in the CI infrastructure.

Update and clean up README.md

The current README.md could be improved in order to add a section for getting started, and then more information like we have today.

Push Puma Editor to the cloud

I would like available puma editor on the Cloud. That's easier to test and start playing than clone the project and run locally.

This feature could help to have a quick adoption by users.

Publish puma task on npm registry

Publish on the npm registry the puma task version 0.1 to be used by other developers. This will enable the tool to be easy integrated into the CI environments as it is today.

instanceof operator expressions are mishandled

Performing binary expressions using the instanceof operator throws an exception. E.g.:

function C(){}
var a = new C();
a instanceof C;

or

function Car(make, model, year) {
  this.make = make;
  this.model = model;
  this.year = year;
}

var mycar = new Car("Honda", "Accord", 1998);
mycar instanceof Car;

Both throw

TypeError: invalid 'instanceof' operand rightResult.value

FirstPass.prototype.visitBinaryExpression() runtime.js:468
FirstPass.prototype.accept() runtime.js:88
FirstPass.prototype.accept() runtime.js:85
FirstPass.prototype.acceptArray() runtime.js:63
FirstPass.prototype.visitProgram() runtime.js:200
FirstPass.prototype.accept() runtime.js:82
FirstPass.prototype.run() runtime.js:70
evalPumaAst() runtime.js:933
evalPuma() runtime.js:928

[[Prototype]] internal property of built-in object types returns <undefined>

The value returned by the [[Prototype]] internal property of the built-in object types when called is not properly handled, and thus remains undefined when used.

E.g.:

var persona = Object.create(Object.prototype, { name: { value: 'Nadia' } });

TypeError: undefined is not an object or null

Object.prototype.constructor;

TypeError: Cannot use 'in' operator to search for 'constructor' in undefined

When using user-defined object types the problem does not produce, e.g.:

function Car(make, model, year) {
  this.make = make;
  this.model = model;
  this.year = year;
}

Object.create(Car.prototype, { make: {value:'Tesla'}, model: {value:'S'}, year: {value:2016} });

Update Wiki

Update the list of team members. Add to git page some hot topics like git flow. Create new entries to help new member in the ramp up.

Metafuncion tag not working properly

I have a meta function calling another meta function and that's not working.
If i don't use the meta tag for the second function, it does work.

/**
 * @meta
 */
function alertSetIntervalVulnerability() {
    var newFunctionPuma = puma.pumaFindByType(pumaProgram, "ExpressionStatement");
    for (var index = 0; index < newFunctionPuma.length; index++) {
        findSetIntervalVulnerability(newFunctionPuma[index]);
    }
    return null;
}
/**
 * @meta
 */
function findSetIntervalVulnerability(setIntervalAst) {
    var expression = setIntervalAst.expression;
    if (expression.type === 'CallExpression') {
        var nombre = expression.callee.name;
        if (nombre === 'setInterval') {
            var parametro = expression.arguments[0];
            if (parametro.type === 'Literal') {
                console.log('La función setInterval que ha definido puede ser un potencial problema de seguridad');
            }
        }
    }
}

delete operator expressions not working properly

Using the delete operator to remove a property from an object doesn't work. E.g.:

s1 = Object({Name:'LEO', Terminal:25000, Destination:'Panchaea'});
delete s1.Destination;
Object.getOwnPropertyNames(s1);

Add shortcuts for editor functions and improve local storage backup.

Add shortcuts for the editor functions so they can be called through a key combination. E.g.

CTRL+X for executing the current code.
CTRL+L for loading saved state.

Useful for faster execution and would help when large pieces of code are introduced on the editor for testing.

Improve the saving of states to the local storage by making them more intuitive or providing a quick sum-up of the availability of this function. A save button for stashing the current state could also be provided.

Creating instances of built-in object types throws TypeError

Using the new operator to create an instance of a built-in object type throws a TypeError exception. E.g.
new Object();

FirstPass.visitNewExpression @ runtime.js:796
image
FirstPass.accept @ runtime.js:154
FirstPass.accept @ runtime.js:85
FirstPass.acceptArray @ runtime.js:63
FirstPass.visitProgram @ runtime.js:200
FirstPass.accept @ runtime.js:82
FirstPass.run @ runtime.js:70
evalPumaAst @ runtime.js:933
evalPuma @ runtime.js:928

Contrarily, creating instances of user-defined object types does not. E.g.

   function Car(make, model, year) {
     this.make = make;
     this.model = model;
     this.year = year;
   }

   var a = new Car('Tesla','S',2016);

Craft a GitHub Pages Website for publishing project information, examples and documentation

GitHub Pages is an easy and rather complete way of documenting a repositories codebase, providing information about the project and releasing use examples and/or code samples.

Being integrated with the repository it's implementation is quite straightforward and easily maintainable:
How to publish, Docs Setting

It's features should be enough for the current implementation as a way of enhancing visibility, providing support and making puma-script more accesible and its use more encouraging.

Optional For expressions not supported

Blank initialization, condition, and update block expressions for the ForStatement aren't supported.
All three of these expressions should be optional, as defined in the ECMA-262v5.1 Standard.

Related tests: test/suites/Tests-12-ECMA.js, lines 185 through 205.

Analysis in meta function

Hello!

I want to do a obfuscation of JavaScript code. For now, I want to add a dummy variable in each for. The example is:

/* @meta */
function meta(){
    var forStatements = puma.pumaFindByType(pumaProgram, 'ForStatement');
    for(var k = 0; k < forStatements.length; k++){
        var forStatement = forStatements[k];
        var declarations = forStatement.init.declarations;
        declarations.push({
            id: {
                type: "Identifier",
                name: "j"
            },
            init: {
                type: "Literal",
                value: 3
            },
            type: "VariableDeclarator"
        });
    }
    return null;
}

The code works.

So, I have one question:
The meta functions are part of puma program so the for sentence inside in my meta function is analyzed too? How avoid this? I want to say, I don't want analyze the for sentence inside in my meta function.

I am using puma-editor for create this example...

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.