/*
 * Copyright 2013 Samsung Information Systems America, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *        http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

// Author: Koushik Sen


Instrument operator is '.   We define the instrument operator recursively by
defining its application on different ast types. We use two auxiliary operators
'' and ''' in the definitions.


B''' => try {
        J$.Fe(iid1, arguments.callee);
        J$.R(iid1, "foo", foo);  // for each function defined in the scope
        B''
    } catch(J$e) {
        throw J$e;
    } finally {
        J$.Fr(iid1);
    }

pgm' => try {
                J$.Se(iid1, script name);
                pgm''
            } catch(J$e) {
                throw J$e;
            } finally {
                J$.Sr(iid1);
            }


(x)'' => x // if x is in scope and not an argument and there is no 'eval' or 'with' in the scope

(x)'' => J$.R(iid1, "x", x)

(x)'' => J$.I(typeof x === "undefined")?J$.R(iid1, "x", undefined):J$.R(iid1, "x", x) // x is in global scope

(e.f)'' => J$.G(iid1, e'', "f")

(e1[e2])'' => J$.G(iid1, e1'', e2'')

(others)'' => others'

(var (x = e)*)' => var (x = e'')*

(new eval(args))' => J$.L(iid1, eval(J$.instrumentCode(args'',true)), N_LOG_OBJECT_NEW)

(new e.f(args))' => J$.L(iid1, J$.M(iid1, e'', "f", true)(args''), N_LOG_OBJECT_NEW)

(new e1[e2](args))' => J$.L(iid1, J$.M(iid1, e1'', e2'', true)(args''), N_LOG_OBJECT_NEW)

(new e(args))' => J$.L(iid1, J$.F(iid1, e'', true)(args''), N_LOG_OBJECT_NEW)

(eval(args))' => J$.L(iid1, eval(J$.instrumentCode(args'',true)), N_LOG_RETURN)

(e.f(args))' => J$.L(iid1, J$.M(iid1, e'', "f", false)(args''), N_LOG_RETURN)

(e1[e2](args))' => J$.L(iid1, J$.M(iid1, e1'', e2'', false)(args''), N_LOG_RETURN)

(e(args))' => J$.L(iid1, J$.F(iid1, e'', false)(args''), N_LOG_RETURN)

(e.f)' => e''.f

(e1[e2])' => e1''[e2'']

(x = e)' => x = J$.W(iid1, "x", e'')

(e1.f)' = e => J$.P(iid1, e1'', "f", e'')

(e1[e2])' = e => J$.P(iid1, e1'', e2'', e'')

(x += e)' => x = J$.W(iid1, "x", x''+e'')

(e1.f += e)'  => J$.A(iid1, e1'', "f", "+")(e'')

(e1[e2] += e)'  => J$.A(iid1, e1'', e2'', "+")(e'')

(C ? e1 : e2)' => C''? e1'' : e2''

(throw e)' => throw e''

(return e)' => return e''

(try B1 catch (x) B2)' => try B1'' catch (x) B2''

(switch(e) (C,B)*)' => switch(e'') (C'', B'')*

(while (C) B)' => while (C'') B''

(for (I; C; S) B)' => for (I''; C''; S'') B''

(do B while (C))' => do B'' while (C'')

(for (x in e1) B)' =>  for (x in e1'') if (x !== "*J$*") B''

(if (C) B1 else B2)' => if (C'') B1'' else B2''

(function(args) B)' => J$.L(iid1, function(args) B''', N_LOG_FUNCTION_LIT);

(function x(args) B)' => function x(args) B''';

(e1 + e2)' => e1'' + e2''

(-e)' => -e''

(delete e1.f)' => delete e1''.f

(delete e1[e2])' => delete e1''[e2'']

(++e)' => (e += 1)'

(e++)' => (e += 1)'-1

(--e)' => (e -= 1)'

(e--)' => (e -= 1)'+1

({props})' =>  J$.L(iid1, {props''}, N_LOG_OBJECT_LIT)

([elements])' =>  J$.L(iid1, [elements''], N_LOG_ARRAY_LIT)

(regex)' =>  J$.L(iid1, regex, N_LOG_REXEXP_LIT)

(stmt)' => stmt''

(e1, e2)' => e1'', e2''

(label: B)' => label: B''

(with (e) B)' => with(e'') B''


