This shows you the differences between two versions of the page.
Next revision | Previous revision | ||
doc:lara [2022/01/15 19:37] jbispo created |
doc:lara [2022/01/15 21:05] (current) jbispo |
||
---|---|---|---|
Line 1: | Line 1: | ||
- | ====== LARA Fundamentals | + | ====== LARA Framework Documentation |
- | The LARA language | + | LARA is a framework written in Java for writing |
+ | LARA scripts can either be plain JavaScript files with the latest EcmaScript syntax (.js files) or EcmaScript 5 (2009) extended with special constructs (.lara files). | ||
- | Recently | + | LARA Framework is open source and available at [[https:// |
- | ==== Aspects ==== | + | |
- | Aspects are regions | + | [Planned Feature] Currently, the starting point of a LARA weaver is always a .lara file, but we are working on support for the entry point to be either |
- | Aspectdef definition | + | /* [[https:// |
- | < | + | [[doc:lara:intro|LARA Introduction]] - Introduction to LARA scripts. |
- | // The main aspect is the first declared in the file | + | |
- | aspectdef MyFirstAspect | + | |
- | // aspect code | + | |
- | end | + | |
- | aspectdef ASecondAspect // An aspect that can be called in the main aspect | + | [[doc: |
- | // aspect code | + | |
- | end | + | |
- | </ | + | |
- | + | [[doc:lara:legacy|Legacy | |
- | + | ||
- | ==== Aspect Inputs and Outputs ==== | + | |
- | + | ||
- | Input parameter definition: | + | |
- | + | ||
- | <code lara> | + | |
- | input | + | |
- | funcs, | + | |
- | opt | + | |
- | end | + | |
- | </ | + | |
- | + | ||
- | Input parameter definition with default values: | + | |
- | + | ||
- | <code lara> | + | |
- | input | + | |
- | funcs = [' | + | |
- | opt = [' | + | |
- | end | + | |
- | </ | + | |
- | + | ||
- | Output definition. Output cannot be initialized inside the **output** block: | + | |
- | + | ||
- | < | + | |
- | output | + | |
- | optFuncs, | + | |
- | code | + | |
- | end | + | |
- | + | ||
- | optFuncs = []; | + | |
- | code = ''; | + | |
- | </ | + | |
- | + | ||
- | ==== Calling Aspects ==== | + | |
- | + | ||
- | Simple aspect call: | + | |
- | + | ||
- | <code lara> | + | |
- | call OptimizeProgram(); | + | |
- | </ | + | |
- | + | ||
- | Calling an aspect with arguments: | + | |
- | + | ||
- | <code lara> | + | |
- | call OptimizeFunctions(functions, | + | |
- | </ | + | |
- | + | ||
- | Calling an aspect with named arguments: | + | |
- | + | ||
- | <code lara> | + | |
- | call OptimizeFunctions(opt: | + | |
- | </ | + | |
- | + | ||
- | + | ||
- | Calling an aspect and retrieving the outputs: | + | |
- | + | ||
- | <code lara> | + | |
- | // Current syntax | + | |
- | var optimizer = call OptimizeFunctions(functions, | + | |
- | + | ||
- | // Previous syntax | + | |
- | call optimizer : OptimizeFunctions(functions, | + | |
- | + | ||
- | var changedFuncs = optimizer.optFuncs; | + | |
- | var finalCode = optimizer.code; | + | |
- | </ | + | |
- | + | ||
- | Assigning an aspect call to a variable for later use. Can still use input arguments and outputs as shown before: | + | |
- | + | ||
- | <code lara> | + | |
- | var optimizer = new OptimizeFunctions(functions, | + | |
- | + | ||
- | call optimizer(); | + | |
- | + | ||
- | var changedFuncs = optimizer.optFuncs; | + | |
- | var finalCode = optimizer.code; | + | |
- | </ | + | |
- | + | ||
- | Aspects can also be called inside Javascript files (.js). You need to build the aspect object and reference the complete path, separated by dollar signs ($): | + | |
- | + | ||
- | <code lara> | + | |
- | // Calling aspect MeasureEnergy from inside a .js file | + | |
- | + | ||
- | (new lara$profiling$Energy$EnergyTest()).call(); | + | |
- | </ | + | |
- | ==== Using LARA Actions ==== | + | |
- | + | ||
- | Actions are used inside apply statements. There are two default actions, **insert** and **def**. Then, it is possible to use weaver-specific actions, which are called with the **exec** keyword: | + | |
- | + | ||
- | <code lara> | + | |
- | select function{' | + | |
- | apply | + | |
- | insert before '/* Creating a clone. */'; | + | |
- | def name = ' | + | |
- | exec clone(' | + | |
- | end | + | |
- | </ | + | |
- | + | ||
- | When calling an action we can specify any join point in the chain to be the action target: | + | |
- | + | ||
- | <code lara> | + | |
- | select function.loop end | + | |
- | apply | + | |
- | $loop.exec tile(8); | + | |
- | $function.insert before '/* This function was transformed. */'; | + | |
- | end | + | |
- | </ | + | |
- | + | ||
- | It is possible to omit the target, the last join point in the chain is used: | + | |
- | + | ||
- | <code lara> | + | |
- | select function.loop end | + | |
- | apply | + | |
- | exec unroll(2); | + | |
- | $loop.exec tile(8); | + | |
- | end | + | |
- | </ | + | |
- | + | ||
- | + | ||
- | If the action returns a result, we can use the following syntax: | + | |
- | + | ||
- | <code lara> | + | |
- | var result = $jp.exec < | + | |
- | </ | + | |
- | + | ||
- | If ' | + | |
- | + | ||
- | <code lara> | + | |
- | | + | |
- | </ | + | |
- | + | ||
- | The keyword ' | + | |
- | + | ||
- | <code lara> | + | |
- | result = $jp.< | + | |
- | </ | + | |
- | + | ||
- | ==== Calling shell commands ==== | + | |
- | + | ||
- | You can invoke shell commands from LARA using the function cmd. The first argument is the command, and the second an array with the arguments for the command: | + | |
- | + | ||
- | <code lara> | + | |
- | + | ||
- | cmd(" | + | |
- | + | ||
- | </ | + | |
- | + | ||
- | + | ||
- | ==== Using LARA from the Command Line ==== | + | |
- | + | ||
- | === Include Folder === | + | |
- | + | ||
- | To add include folders, use the flag -i. To add more than one folder, use double quotes and separate the folders with the file separator character of your current system | + | |
- | + | ||
- | < | + | |
- | + | ||
- | larai -i " | + | |
- | + | ||
- | </ | + | |
- | + | ||
- | === Passing Arguments to the Aspect === | + | |
- | + | ||
- | To pass arguments to the top-level aspect use the flag -av. The input is a JSON representation of the input: | + | |
- | + | ||
- | < | + | |
- | + | ||
- | larai -av " | + | |
- | + | ||
- | </ | + | |
- | + | ||
- | + | ||
- | ==== Codedef Sections ==== | + | |
- | + | ||
- | To insert sections of code that span several lines, you can define codedef sections, which act as templates. Example: | + | |
- | + | ||
- | <code lara> | + | |
- | + | ||
- | codedef CodeTemplate(param1, | + | |
- | // This code is inserted as-is, without escaping | + | |
- | + | ||
- | // To apply the values of parameters, use [[]] | + | |
- | var [[param1]] = [[param2]]; | + | |
- | + | ||
- | }% end | + | |
- | + | ||
- | </ | + | |
- | + | ||
- | Declared codedefs can then be used in the code as functions: | + | |
- | + | ||
- | <code lara> | + | |
- | + | ||
- | code = CodeTemplate(" | + | |
- | + | ||
- | </ | + | |
- | + | ||
- | ====== Miscellaneous ====== | + | |
- | + | ||
- | ==== Regular Expressions ==== | + | |
- | + | ||
- | Lara supports JavaScript regular expressions, | + | |
- | + | ||
- | <code lara> | + | |
- | + | ||
- | var regex = / | + | |
- | regex.test(" | + | |
- | + | ||
- | </ | + | |
- | + | ||
- | Since **exec** is a LARA keyword, calling **regex.exec** is not permitted. However, you can access object properties using strings to circumvent this limitation: | + | |
- | + | ||
- | <code lara> | + | |
- | + | ||
- | (regex[' | + | |
- | + | ||
- | </ | + | |
- | + | ||
- | Alternatively, | + | |
- | + | ||
- | <code lara> | + | |
- | + | ||
- | String(' | + | |
- | + | ||
- | </ | + | |
- | + | ||
- | Or you can also use the **match** boolean operator ( **~=** ): | + | |
- | + | ||
- | <code lara> | + | |
- | + | ||
- | ' | + | |
- | + | ||
- | </ | + | |
- | + | ||
- | ==== Importing LARA Files ==== | + | |
- | + | ||
- | LARA supports importing LARA files (with extension .lara) that are present in the include path (flag -i) using the keyword **import**. To import a file, you have to use the path to the file from the include folder, using ' | + | |
- | + | ||
- | <code lara> | + | |
- | + | ||
- | import bar.Aspect; | + | |
- | + | ||
- | </ | + | |
- | + | ||
- | Import statements must be the first statements in a LARA file. LARA weavers come bundled with support for a set of imports, which are part of their API (e.g., [[http:// | + | |
- | + | ||
- | ==== Importing JS Files ==== | + | |
- | + | ||
- | All JS files (with extension .js) that are present in folders of the include path are automatically evaluated before any LARA file. However, there is a mechanism for importing specific JS files at the same time as LARA files. | + | |
- | + | ||
- | When the name of a folder of the include path ends with ' | + | |
- | + | ||
- | <code lara> | + | |
- | + | ||
- | import bar.Foo; | + | |
- | + | ||
- | </ | + | |
- | + | ||
- | + | ||
- | If the folder contains both a Foo.lara and a Foo.js, both files are imported, first the LARA file, and then the JS file. This can be useful if the JS file needs specific imports (the keyword **import** is LARA-specific and is not supported | + | |
- | + | ||
- | Furthermore, | + | |
- | + | ||
- | Since LARA is based on an older version of JS (i.e. EcmaScript 5), many recent JavaScript features are not available in LARA code. We recommend using JS files in order to have access to more recent features of JavaScript. Currently the LARA framework supports EcmaScript 2021 for JS files. | + | |
- | ==== Reading/ | + | |
- | + | ||
- | LARA supports reading from and writing to JSON objects with the object **Io**: | + | |
- | + | ||
- | /* <code lara> */ | + | |
- | <code javascript> | + | |
- | import lara.Io; | + | |
- | + | ||
- | ... | + | |
- | + | ||
- | Io.writeJson(" | + | |
- | var loadedObject = Io.readJson(" | + | |
- | </ | + | |
- | + | ||
- | + | ||
- | ==== Testing Join Point Types ==== | + | |
- | + | ||
- | To test if a join point is of a certain type, use the attribute '' | + | |
- | + | ||
- | ====== Legacy LARA ====== | + | |
- | + | ||
- | This section contains LARA constructs that are still valid, but for which newer (and recommended) alternatives exist. | + | |
- | + | ||
- | ==== Select ==== | + | |
- | + | ||
- | (Alternative: | + | |
- | + | ||
- | Select with full join point chain: | + | |
- | + | ||
- | <code lara> | + | |
- | select program.file.function.body.loop end | + | |
- | </ | + | |
- | + | ||
- | Select with only last join point. The chain is induced, produces the same result as above: | + | |
- | + | ||
- | <code lara> | + | |
- | select loop end | + | |
- | </ | + | |
- | + | ||
- | Assign the selected join points to a variable for later use: | + | |
- | + | ||
- | <code lara> | + | |
- | LOOPS: select loop end | + | |
- | </ | + | |
- | + | ||
- | Assign an alias for specific join points: | + | |
- | + | ||
- | <code lara> | + | |
- | select ($p=loop).($c=loop) end | + | |
- | </ | + | |
- | + | ||
- | ==== Apply ==== | + | |
- | + | ||
- | (Alternative: | + | |
- | + | ||
- | Apply after a select: | + | |
- | + | ||
- | <code lara> | + | |
- | select loop end | + | |
- | apply | + | |
- | println($loop.rank); | + | |
- | end | + | |
- | </ | + | |
- | + | ||
- | Apply on a previously selected set of join points: | + | |
- | + | ||
- | <code lara> | + | |
- | apply to LOOPS | + | |
- | println($loop.rank); | + | |
- | end | + | |
- | </ | + | |
- | + | ||
- | It is possible to perform a natural join on two sets of join points: | + | |
- | + | ||
- | <code lara> | + | |
- | LOOP_START: select function.body.loop.($loop_start = first) end | + | |
- | FUNCTION_FIRST: | + | |
- | + | ||
- | apply to LOOP_START:: | + | |
- | // Init counters at the beginning of the function | + | |
- | $first.insert before%{counter_[[$loop.uid]] = 0;}%; | + | |
- | + | ||
- | // Increment counters when entering the loop | + | |
- | $loop_start.insert before%{counter_[[$loop.uid]] = counter_[[$loop.uid]] +1;}%; | + | |
- | + | ||
- | // ... | + | |
- | end | + | |
- | </ | + | |
- | + | ||
- | Use of join points with aliases inside the apply statement: | + | |
- | + | ||
- | <code lara> | + | |
- | select ($p=loop).($c=loop) end | + | |
- | apply | + | |
- | | + | |
- | end | + | |
- | </ | + | |
- | + | ||
- | ==== Conditions ==== | + | |
- | + | ||
- | (Alternative: | + | |
- | + | ||
- | Using a condition block: | + | |
- | + | ||
- | <code lara> | + | |
- | select function end | + | |
- | apply | + | |
- | // ... | + | |
- | end | + | |
- | condition | + | |
- | $function.name == ' | + | |
- | end | + | |
- | </ | + | |
- | + | ||
- | Combining conditions using && (and) and || (or) operators: | + | |
- | + | ||
- | <code lara> | + | |
- | select loop end | + | |
- | apply | + | |
- | $loop.exec Unroll(2); | + | |
- | end | + | |
- | condition | + | |
- | $loop.is_innermost && | + | |
- | $loop.type==" | + | |
- | end | + | |
- | </ | + | |
- | + | ||
- | Using " | + | |
- | + | ||
- | <code lara> | + | |
- | select function{name==' | + | |
- | apply | + | |
- | // ... | + | |
- | end | + | |
- | + | ||
- | // OR | + | |
- | select function{' | + | |
- | apply | + | |
- | // ... | + | |
- | end | + | |
- | </ | + | |