Let's write a compiler using LLVM. Since LLVM (Low Level Virtual Memory) manages the generation and the execution of native binary code, we only need to focus on the part that read our program source code and makes all LLVM API calls.
BrainF**k is a good introduction to compiler programmation because it use much of basic tools of LLVM API, needed to create more complex compiler.
BrainF**k language is very easy: the internal structure is composed of an array of cells and a cursor. The cursor allows to access (read or write) a cell and each cell contains a number (basically from 0, by default, to 255, to be output as ASCII).
You've got 8 operations:
'<' and '>' to move the cursor to access another cell (move to left and right) '+' and '-' to change the value of the current cell, where the cursor stands (to increment and decrement) ',' and '.' to input (ask the user a value to set) and to output (print the value) the current cell '[' and ']' to do conditional looping depending of the current cell value (enter the loop the current celle value > 0 and exit if it equals to 0)
For example, this dummy program:
>><+++<++>--[->+<]>.
will gives the output: 1
The state of cells and cursor at the end of the execution is:
cells : [2][0][1] cursor: ^
Detailled operations:
>> : set cursor to 0 + 2 = 2 < : set cursor to 2 - 1 = 1 +++ : add 3 to current cell value ([1] = 3) < : set cursor to 1 - 1 = 0 ++ : add 2 to current cell value ([0] = 2) > : set cursor to 0 + 1 = 1 -- : subtract 2 to current cell value ([1] = 3 - 2 = 1) [ : enter the loop since the current cell value > 0 ([1] = 1) - : subtract 1 to current cell value ([1] = 1 - 1 = 0) > : set cursor to 1 + 1 = 2 + : add 2 to current cell value ([2] = 0 + 1 = 1) < : set cursor to 1 - 1 = 1 ] : exit the loop since the current cell value is 0 > : set cursor to 1 + 1 = 2 . : print the current cell value ([2] = 1)
The definition of a compiler is a program that transform a format of file to another. For example, XSD allows to transform XML to HTML, Dart compiler to transform Dart script to Javascript, etc. In our case, we want our compiler to transform BrainF**k files to native code, for x86, ARM or else.
For flexibility reasons, we compile (transform) our BF file to an intermediate language (much lower level) and LLVM compiles this to assembler, which once linked, gives native binary. Hopefully, most works are done by LLVM like assembler generation, we only need to compile our input file to this intermediate language, called Intermediate Representation. This kind of compiler is called a front-end for LLVM (generate IR form input file). The compiler which generate assembler from IR is called a back-end.
Intermediate language allows low-level optimisations and is totally platform independent, so this representation program will be exactly the same even if you want to generate binary code to x86, ARM or Sparc architecture. Basically, intermediate language allows memory operation (allocation, reading and writing data from/to memory), arithmetic operation (add, mul, xor, etc.), basic data structure (c-like struct and array) and integration to external c-function (printf, scanf, etc.).
|-- Front-end --| |-- Back-end --| [Source code] -> [Parser] --- LLVM API --> [IR (Intermediate Representation)] -> [Compilation] -> [Native binary] -> [Execution] -> [Output] |-- LLVM (Low Level Virtual Machine) --|
For example, clang (C/C++ compiler based on LLVM) will follow this schema:
|- clang -| [C/C++ code source] -> [Parser] -> [IR] -> [Compilation] -> [Native binary] -> [Execution] -> [Output] |-- hello.c --| |-- $ clang hello.c -o hello --| |-- $ ./hello --|
As LLVM is a "Virtual Machine", it also can execute code without to generate native binary, following this schema:
|-- Front-end --| [Source code] -> [Parser] --- LLVM API --> [IR (Intermediate Representation)] -> [Execution] -> [Output] |-- LLVM (Low Level Virtual Machine) --|
The performance are the same that a native binary, it's just a convenient way to execute native code without to export a binary. You can choose, once the IR generate from your compiler, to execute native code from the Virtual Machine or to export native binary.
Simply, to install the lasted version of LLVM with git:
$ git clone http://llvm.org/git/llvm.git $ cd llvm/ $ ./configure $ sudo make install
More informations on installation wiki.
First, we need to get tokens from our BF program. We will ignore (skip) all characters that are not BF commands (note that we use char, not string):
bool Parser::isSkipable(char c) { return (c != '<' && c != '>' && c != '+' && c != '-' && c != '.' && c != ',' && c != '[' && c != ']'); }
The method getToken
returns the next valid character (token).
The while
loop will stop when c
will be equal to zero, and since the last character of _data
(at index index
) is zero (null-character terminated string), the method will stop when it reaches the end of the string.
Since we want to skip ignored character, the while
will loop until a non-ignored character is found (or the end of the string).
char Parser::getToken() { char c = 0; while ( (c = _data[_index++]) && isSkipable(c) ) { } return c; }
Note: the while ( (var = value) ) { }
pattern is common, it's a shorter way to do:
while (1) { var = value; if (var == 0) { break; } }
Note the extra parenthesis (var = value)
, this not evaluates the assignment (always true) but the value of the variable assigned, var
in this case; if var
is greater than zero, the while
loop continues to loop. A warning (with -Wall
) shows up if the extra parenthesis are missing.
Now, we can create our parser class:
class Parser { protected: string _data; int _index; static bool isSkipable(char c); char getToken(); public: Parser(string s) : _data(s), _index(0) { } };
The default constructor will take a string, the program, store it into _data
and will parse it.
Note: Be careful to hide (under protected:
or private:
) all method and variables that shouldn't be accessed outside the class.
The protected getToken()
method is a good example, we don't want to access (and modify _index
) outside the parser class.
For debugging propose, we will expose protected and private variables and methods, don't forget to hide them after tests.
Usage:
class Parser { protected: string _data; int _index; static bool isSkipable(char c); -- char getToken(); public: Parser(string s) : _data(s), _index(0) { } ++ char getToken(); }; string s = ">>+++ <<3 + >++ < 123 abc .>.>."; Parser parser(s); char c = 0; while ( (c = parser.getToken()) ) { cout << c << " "; }
This writes out: > > + + + < < + > + + < . > . > .
and ignored characters are ignored indeed.
Put back the getToken()
method into protected section.
Let's now write the parse()
method.
We will use the pattern from the last example but we will create a case for each item:
class Parser { protected: string _data; int _index; static bool isSkipable(char c); char getToken(); ++ void parse(); public: Parser(string s) : _data(s), _index(0) { parse(); } }; ++ void Parser::parse() ++ { ++ char c = 0; ++ while ( (c = getToken()) ) { ++ switch (c) { ++ case '<': ++ cout << "go to left" << endl; break; ++ case '>': ++ cout << "go to right" << endl; break; ++ case '+': ++ cout << "add one" << endl; break; ++ case '-': ++ cout << "substract one" << endl; break; ++ case '.': ++ cout << "print" << endl; break; ++ case ',': ++ cout << "ask for value" << endl; break; ++ case '[': ++ cout << "start loop" << endl; break; ++ case ']': ++ cout << "end loop" << endl; break; ++ default: break; // Ignored character ++ } ++ } ++ }
Now our parser knows how to handle each character, we use it to create a AST (Abstract Structure Tree) where we will create an object for each case.
Let's begin with the "move to" operation and we will call it the "shift" expression. We can create a single shift expression for right and left, the first add one to cursor (+1), the latter remove one (-1) and we need to check that the cursor can't be less than zero.
The class looks like this:
class ShiftExpr { protected: int _step; public: ShiftExpr(int step) : _step(step) { } };
We will inherit this class from an abstract (virtual) Expr
class which contains a public CodeGen()
method to generate the LLVM code, we will see the implementation later.
class Expr { public: virtual void CodeGen() = 0; };
and we update our ShiftExpr
to inherite from Expr
publicly to allow polymorphism:
class ShiftExpr : public Expr { protected: int _step; public: ShiftExpr(int step) : _step(step) { } void CodeGen(); }; void ShiftExpr::CodeGen() { // We will implement this later }
Now, we will use this class into the parse method. This create an shift expr which could generate LLVM bitcode. Expressions will be stored into a vector (some sort of array).
#include <vector>
class Parser { protected: string data; int index; ++ vector<Expr *> exprs; static bool isSkipable(char c); char getToken(); void parse(); public: Parser(string s) : data(s), index(0) { parse(); } }; void Parser::parse() { char c = 0; while ( (c = getToken()) ) { ++ Expr *expr = NULL; switch (c) { case '<': { ++ expr = new ShiftExpr(-1); // Shift to the left ++ } break; case '>': { ++ expr = new ShiftExpr(1); // Shift to the right ++ } break; case '+': cout << "add one" << endl; break; case '-': cout << "substract one" << endl; break; case '.': cout << "print" << endl; break; case ',': cout << "ask for value" << endl; break; case '[': cout << "start loop" << endl; break; case ']': cout << "end loop" << endl; break; default: break; // Ignored character } ++ if (expr) { ++ exprs.push_back(expr); ++ } } }
And we will create three more expressions: IncrementExpr
, InputExpr
and OutputExpr
like that:
class IncrementExpr : public Expr { protected: int _increment; public: IncrementExpr(int increment) : _increment(increment) { } void CodeGen(); }; void IncrementExpr::CodeGen() { // We will implement this later }
class InputExpr : public Expr { public: InputExpr() { } void CodeGen(); }; void InputExpr::CodeGen() { // We will implement this later }
class OutputExpr : public Expr { public: OutputExpr() { } void CodeGen(); }; void OutputExpr::CodeGen() { // We will implement this later }
And, again, update the parse()
method:
void Parser::parse() { char c = 0; while ( (c = getToken()) ) { Expr *expr = NULL; switch (c) { case '<': { expr = new ShiftExpr(-1); // Shift to the left } break; case '>': { expr = new ShiftExpr(1); // Shift to the right } break; case '+': { ++ expr = new IncrementExpr(1); // Increment (add 1) ++ } break; case '-': { ++ expr = new IncrementExpr(-1); // Decrement (substract 1) ++ } break; case '.': { ++ expr = new OutputExpr(); // Output value ++ } break; case ',': { ++ expr = new InputExpr(); // Output value ++ } break; case '[': cout << "start loop" << endl; break; case ']': cout << "end loop" << endl; break; default: break; // Ignored character } ++ if (expr) { ++ exprs.push_back(expr); ++ } } }
Now, a little bit more complicated: the loop. A loop starts with [
and ends ]
. The program enters the loop only if the value at the current cursor is greater than zero and the program ends the loop only if the value at the current cursor is equal to zero. We will see later how to create a loop with LLVM IR language but for now, we only need to create a new class LoopExpr
which contains all expressions inside the loop.
As a loop can contain other loops, we will use recursive calls of parse()
function, so we need to modify this method to allow reccursivity. In place for calling the function with no arguments, we will use the vector which holds parser expressions as argument.
The new version of the prototype is simply:
void Parser::parse(vector&exprs);
and the implementation doesn't change.
Also, we need to change the calling into the default constructor:
Parser(string s) : data(s), index(0) { parse(exprs); }
Note: Don't confound the initialisation of instance variables, after the :
and the calling of a method inside the method body. These cases aren't correct:
Parser(string s) : data(s), index(0), parse(exprs) // error { }
Parser(string s) { data(s); index(0); // error parse(exprs); }
If you are not confident with this writing, you could also write this:
Parser(string s) { data = s; index = 0; parse(exprs); }
Now, let's write our LoopExpr
class, which be initialised with a vector of expressions:
class LoopExpr : public Expr { protected: vector_exprs; public: LoopExpr(vector &exprs) : _exprs(exprs) { } void CodeGen(); }; void LoopExpr::CodeGen() { // We will implement this later }
We create the vector when the parser will find a start loop character [
:
void Parser::parse(vector&exprs) { char c = 0; while ( (c = getToken()) ) { Expr *expr = NULL; switch ( c ) { case '<': { expr = new ShiftExpr(-1); // Shift to the left } break; case '>': { expr = new ShiftExpr(1); // Shift to the right } break; case '+': { expr = new IncrementExpr(1); // Increment (add 1) } break; case '-': { expr = new IncrementExpr(-1); // Decrement (substract 1) } break; case '.': { expr = new OutputExpr(); // Output value } break; case ',': { expr = new InputExpr(); // Output value } break; case '[': { ++ vector loopExprs; ++ parse(loopExprs); // Enter into a new function ++ expr = new LoopExpr(loopExprs); } break; case ']': { ++ return ; // Exit the function } default: break; // Ignored character } if (expr) { exprs.push_back(expr); } } }
Each time the parser will find a [
character, it will call the same method parse(vector<Expr *> &exprs)
method and when it will found the associated ]
, it will quit this function.
Let's look at this simple BF example:
++[+[-]]
At the beginning, we initialising the parser and calling the parse
method. Then, the current cell is incrementing by two before entering the loop. The parser finds a start loop character [
so it calls the parse
method again by passing a empty vector argument.
The parser will continue from the current token, after the [
(inside the loop) and will parsing the next +
, which increment again the current cell. Then, another [
is found, and the parser will one time more calls the parse
method with a new brand vector argument. A this time, no LoopExpr
is yet created, not until a matching ]
is found. The trace looks like:
parse this: "++[+[-]]" { // '+' found // '+' found // First '[' found here, call 'parse' parse this: "+[-]]" { // '+' found // Another '[' found here, call 'parse' parse this: "-]]" { // We are here } } }
Next, we decrement the current cell and a matching ]
is found, it's time to exit the current loop. At this precise time, the parse
method exits and the parser goes on by creating an instance of LoopExpr
by passing the vector wich contains an instance of IncrementExpr
, created from the previous -
character. Then, another ]
is found, create a LoopExpr
with previous expression and exit. The trace looks like:
parse this: "++[+[-]]" { // '+' found // '+' found // First '[' found here, call 'parse' parse this: "+[-]]" { // '+' found // Another '[' found here, call 'parse' parse this: "-]]" { // '-' found // A ']' found here, create a 'LoopExpr' with '-' and exit return } // A ']' found here, create a 'LoopExpr' with: '+' and the previous 'LoopExpr' (which contains '-') // and then, exit return } // End of program }
As the parse()
method takes a reference to a vector, with can modify it inside the method and getting a up-to-date version when the method exits, needed to create an new LoopExpr
instance (we could also return the vector when exiting the method but this latter solution required to create a copy of a vector, which can more expensive that using a reference).
We also need to add a CodeGen()
method to Parser, it will be the entry point to generate native code from the vector of expressions:
/** Parser.h **/ class Parser { protected: std::string data; int index; std::vector_exprs; static bool isSkipable(char c); char getToken(); void parse(std::vector &exprs); public: Parser(std::string s) : data(s), index(0) { parse(_exprs); } ++ void CodeGen(Module *M, IRBuilder<> &B); void DebugDescription(int level); };
/** Parser.cpp **/ ++ void Parser::CodeGen(Module *M, IRBuilder<> &B) ++ { ++ }
Now our whole is about 200 lines of code, it's time for refactoring!
The idea is to separate part into different files like BrainF.cpp
with out main
function, Parser.cpp
for the Parser
class, Expr.cpp
for *Expr
classes and CodeGen.cpp
for all *Expr::CodeGen()
methods implementation (as we will see, this file could be the biggest file of the program, it's important to separate from *Expr
classes definition).
Let's create Brain.cpp
, Expr.cpp
and CodeGen.cpp
but also header files like so:
- BrainF.h - BrainF.cpp - Parser.h - Parser.cpp - Expr.h - Expr.cpp - CodeGen.h - CodeGen.cpp
Move Parser
class definition to Parser.h
and implementation to Parser.cpp
. I recommend the header file to looks like
#ifndef PARSER_H #define PARSER_H #include#include "Expr.h" // Class declaration here #endif // PARSER_H
The define, like PARSER_H
(uppercase path, folder/my_file.h
could become FOLDER_MY_FILE_H
), is used to avoid multiple inclusion [link].
We need to update the Makefile
to include all *.cpp
files:
all: build run build: Expr.cpp CodeGen.cpp Parser.cpp BrainF.cpp clang++ Expr.cpp CodeGen.cpp Parser.cpp BrainF.cpp -o BrainF run: BrainF ./BrainF
Note: To follow LLVM coding rules for the API:
|
, like |varName|
Examples:
llvm::Variable *CountV = ...; llvm::Type *IntTy = ...; llvm::BasicBlock *LoopBB = ...; llvm::IRBuilder<> LoopB(LoopBB);
Or with explicit namespace (preferred):
namespace llvm; Variable *CountV = ...; Type *IntTy = ...; BasicBlock *LoopBB = ...; IRBuilder<> LoopB(LoopBB);
We now update our XXXExpr::CodeGen
method to pass the module and the IR Builder to generate IR code.
llvm:Module
contains informations about locals and globals variables, functions, etc. We will only use a single module in our parser.
llvm::IRBuilder<>
is a template to add instructions to the current module.
void Parser::CodeGen(Module *M, IRBuilder<> &B) { // @TODO: Initialise the native code generator (initialise variables, etc.) // @TODO: Recursively generate code by calling `CodeGen(M, B)`on each expression } void ShiftExpr::CodeGen(Module *M, IRBuilder<> &B) { // @TODO: Add |_step| to the current index } void IncrementExpr::CodeGen(Module *M, IRBuilder<> &B) { // @TODO: Add |_step| to the current cell } void InputExpr::CodeGen(Module *M, IRBuilder<> &B) { // @TODO: Call "scanf" std function // @TODO: Put the input value to the current cell } void OutputExpr::CodeGen(Module *M, IRBuilder<> &B) { // @TODO: Call "printf" std function } void LoopExpr::CodeGen(Module *M, IRBuilder<> &B) { // @TODO: Create a loop // @TODO: Enter the loop only if the current cell value is greater than zero // @TODO: Exit the loop if the current cell value is equal to zero }
Into the Parser
method, we will first create two global variables (the opposite of local variable) for the index and cells, and initialise them.
The second step is to recursively call CodeGen()
on each *Expr
from |_expr|, with a simple for loop.
void Parser::CodeGen(Module *M, IRBuilder<> &B) { // @TODO: Create |index| global variable // @TODO: Initialise |index| global variable // @TODO: Create |cells| global variable // @TODO: Initialise |cells| global variable // Recursively generate code for (std::vector::iterator it = _exprs.begin(); it != _exprs.end(); ++it) { (*it)->CodeGen(M, B); } }
For the Shift
expression, it simple but we need to decompose each part. To change the value of a variable, the computer need 3 steps:
Load the value at the given address (the pointer of the |index|
global variable)
Create a temporary variable to store the result of the operation: |index| + |step|
Save the temporary variable value at the |index|
address
void ShiftExpr::CodeGen(Module *M, IRBuilder<> &B) { // @TODO: Get the value of |index| global variable // @TODO: Create a temporary variable that contains the |index| + |_step| result // @TODO: Save the "index" global variable }
It can look complicated but it's what your computer does every time it add two value from memory.
It should be easy for you now to understand this basic IR code (all variables start with "%"):
; This is a comment %index = load %index_addr ; Load the address from (the given) |index_addr| to |index| (created) %temp = add %index, 1 ; Create |temp| variable with the result of |index| + 1 store %temp, %index_addr ; Save (store) the value of |temp| at address |index_addr|
The IncrementExpr
uses the same principle but this time, we need to load "index" first to get the value from "cells" at a specific index, the |index|
value (the name makes sense now!).
Once we've got "index", we need to compute the offset to get the cell value, load it, create a temporary variable to store the addition then save it back:
void IncrementExpr::CodeGen(Module *M, IRBuilder<> &B) { // @TODO: Get the value of |index| global variable // @TODO: Compute the offset of |cells| array based on |index| // @TODO: Load the offset address from |cells| // @TODO: Create a temporary variable that contains the |cells|[|index|] + |_step| result // @TODO: Save the temporary variable at address |cells|[|index|] }
Note: You could ask why we use the add
operator for decrement and not sub
, since it's more natural. In old days for computing, add -1
was generally much faster than sub 1
but with modern architectures, it's different, and the best way is to let LLVM decides which platform-dependant optimisations will be made. Since IR code is platform independent, we can even not provide an hint for this. Just keep that LLVM will certainly knows better what to optimise and it's better to focus on algorithm and data structures optimisation than these silly ones, and keep the code simple and clear for everyone.
The InputExpr
expression, we will simply use the scanf
C function, LLVM will link to it during compilation. We just need to pass arguments to this function and call it. The single catch is to create a global variable to store the format string, but we already know how to do it.
void InputExpr::CodeGen(Module *M, IRBuilder<> &B) { // @TODO: Prepare arguments (format string and input char) // @TODO: Call "scanf" std function // @TODO: Get the value of |index| global variable // @TODO: Compute the offset of |cells| array based on |index| // @TODO: Save the temporary variable at address |cells|[|index|] (no operation, just overwrite) }
The OutputExpr
expression is simply a call to printf
C function:
void OutputExpr::CodeGen(Module *M, IRBuilder<> &B) { // @TODO: Get the value of |index| global variable // @TODO: Compute the offset of |cells| array based on |index| // @TODO: Load the offset address from |cells| // @TODO: Prepare arguments (format string and the current cell value) // @TODO: Call "printf" std function }
The Loop
expression is more complex since the comportment will depend of current cell value, like enter the loop if the current cell value is greater to zero and exit if this value if equal to zero. If we need to make choice depending to value (at runtime), we need to use block and branches.
A block is simply instructions that we separate to other piece of code, we can jump to the block, skip it or even loop by calling it at the end of itself. Since block is a basis of LLVM IR code structure, they are referred as Basic blocks
and are so useful that every function (like the main
one) starts with a block.
In some way, blocks are like function, we can call them (using branches) but we can't pass argument to it, therefore variables created before the branch is made are still accessible.
Branches are equally useful since a block must be call by a branch (except the first block of a function, called EntryBlock
) and must finish by a branch or a ret
(return, to exit a function) instruction. Branches can be conditional or direct.
Basic blocks are constructed like so:
; Previous instructions br %LoopBlock ; Direct branching to "LoopBlock" LoopBlock: ; Loop instructions %result = icmp eq i32 %i, 0 ; CoMPare as Int (icmp with int32) if %i is EQual (eq) to 0, %i equal 1 (true), else 0 (false) br i1 %result, label %DoneBlock, label %LoopBlock ; If %result (boolean, of type int1) is true, branch to DoneBlock, else to LoopBlock DoneBlock: ; Next instructions
For out Loop
expression to work correctly, we need to check before entering the loop if the current cell value is greater than 0 (Signed Greater Than, or sgt
of LLVM) and checking at the end of the loop is the value is equal to 0 to exit the loop. We can resume the structure our loop to:
; Previous instructions of our program br %StartLoopBlock StartLoopBlock: ; @TODO: Load current cell value and put it into %value %enterLoop = icmp sgt i32 %value, 0 ; if (%value > 0), enter the loop, else skip the loop br i1 %enterLoop, label %LoopBlock, label %EndLoopBlock LoopBlock: ; Loop instructions ; @TODO: Load current cell value and put it into %value br %StartLoopBlock ; Restart the loop (will exit if current cell value > 0) EndLoopBlock: ; Next instructions of our program
Note: a block must existing before branching to it. It's generally more clear to add the branching instruction before adding instructions to it. For example, the following branching:
; Previous instructions br %MyBlock MyBlock: %3 = add %1, %2; Dummy addition for example br %MyBlock2 MyBlock2: ; Next instructions
will be decomposed as follow from API:
// Create "MyBlock" block // Add branch to "MyBlock" // Add "add" instruction into "MyBlock" // Create "MyBlock2" block // Add branch to "MyBlock2"
We update our CodeGen
function comments:
void LoopExpr::CodeGen(Module *M, IRBuilder<> &B) { // @TODO: Create the "StartLoop" block // @TODO: Create branch to "StartLoop" // @TODO: Get the value of "index" global variable // @TODO: Compute the offset of "cells" array based on "index" // @TODO: Compare current cell value with zero // @TODO: Create the "Loop" block // @TODO: Create the "EndLoop" block // @TODO: Create conditional branch to %LoopBlock or %EndLoopBlock // @TODO: Generate instructions from |_exprs| // @TODO: Restart loop }
To create a global variable, with need to specify the type and the initialisation value:
Module *M = // Default module LLVMContext &C = M->getContext(); // Get the current context (an opaque part of LLVM that contains state about the program execution) Type *Ty = Type::getInt32Ty(C); // 32 bits integer type const APInt Zero = APInt(32, 0); // 32 bits integer with value zero Constant *InitK = Constant::getIntegerValue(Ty, Zero); // Create a constant with the int32 value zero __BrainF_IndexPtr = new GlobalVariable(*M, // Use default module Ty, // 32 bits integer false, // non-constant GlobalValue::WeakAnyLinkage, // Keep one copy when linking (weak) InitK, // Initialise with constant zero "brainf.index" // Call this global variable "brainf.index" );
And since with will use it as global variable into our program, we will declare it static:
static GlobalVariable *__BrainF_IndexPtr = NULL;
and be sure that we initialise it only once:
if (!__BrainF_IndexPtr) { // Initialisation goes here }
For the cells array, it's the same way but we need the declare the exact size of it. Hundred cells seem correct for most programs:
#define kCellsCount 100 ArrayType *ArrTy = ArrayType::get(Type::getInt32Ty(C), kCellsCount); // An array type of 100 x int32 std::vectorconstants(kCellsCount, B.getInt32(0)); // Create a vector of 100 items equal to 0 ArrayRef Constants = ArrayRef (constants); // Create an array of 100 constants equal to 0 Constant *InitPtr = ConstantArray::get(ArrTy, Constants); // Create a pointer to this global array __BrainF_CellsPtr = new GlobalVariable(*M, // Use default module ArrTy, // an array of 100 x int32 false, // non-constant GlobalValue::WeakAnyLinkage, // Keep one copy when linking (weak) InitPtr, // Initialise with the array "brainf.cells" // Call this global variable "brainf.cells" );
And we need to also declare it:
static GlobalVariable *__BrainF_CellsPtr = NULL;
and be sure that we initialise it only once:
if (!__BrainF_CellsPtr) { // Initialisation goes here }
Now that __BrainF_IndexPtr
and __BrainF_CellsPtr
are pointer to respectively int32 and [100 x int32], we need to do some work to get the value.
For the __BrainF_IndexPtr
, it's simply a pointer to int32, noted *int32
. To read it, we need the load
instruction, the result will be the value that the pointer contains (i.e.: the value stored in memory at this address).
In IR, this gives:
%index = load %brainf.index
And with LLVM API, this is:
IRBuilder<> &B = // Use current builder Value *IdxV = B.CreateLoad(__BrainF_IndexPtr);
The save operation is simple: put a value at the pointer but there is a catch, the value must be of the same type that the base pointer type. For example, you have to save a int32
into a *int32
, you can't save a int8
or int64
into it, you have to cast the value. Without casting, an assert will be thrown when executing the bitcode.
The save operation is done with the store instruction (which returns nothing):
store %index, %brainf.index ; OK, %index is int32 and %brainf.index is *int32
And with LLVM API, this is:
// Get value for "brainf.index" Value *IdxV = B.CreateLoad(__BrainF_IndexPtr); // %1 = load %brainf.index // Add 10 to |IdxV| Value *NewIdxV = B.CreateAdd(IdxV, B.getInt32(10)); // %2 = add int32 %1, 10 // Save it back B.CreateStore(IdxV, __BrainF_IndexPtr); // store %2, %brain.index
Now, the value of brainf.index
is 10, and the ShiftExpr
simply becomes:
void ShiftExpr::CodeGen(Module *M, IRBuilder<> &B) { // Get the value of "index" global variable Value *IdxV = B.CreateLoad(__BrainF_IndexPtr); // Create a temporary variable that contains the "index" + |_step| result Value *ResV = B.CreateAdd(IdxV, B.getInt32(_step)); // Save the "index" global variable B.CreateStore(ResV, __BrainF_IndexPtr); }
We now need to access to cells.
It's really important to note that __BrainF_CellsPtr
is a pointer to an array (since we create a global variable), for LLVM it's a [i32 x 100]*
. To access to the 3rd element of this array, we will use the Get Element Pointer
method (generally noted as GEP
). This computes the memory offset that we need to access a specific element of an array but it's really important to note that this method never access to memory, it only do some calculation (that we can of course also do by our own). The idea is simple: from a pointer, we provide an array of integer of offsets to access to a specific element.
In our example, we've got a pointer to an array, if we need to access to the 3rd element, we need two steps:
[i32 x 100]*
to [i32 x 100]
: offset 0[i32 x 100]+3
: offset 3
Our offsets array is [0, 3]
and the final instruction %third_element = getelementptr %brainf.index, 0, 3
With LLVM API, this gives:
ArrayRefIdxsArr((Value* []){B.getInt32(0), B.getInt32(3)}); // Create the array of offsets: [0, 3] Value *CellPtr = B.CreateGEP(__BrainF_CellsPtr, IdxsArr); // %cell = getelementptr %brainf.index, 0, 3
Since getelementptr
doesn't acces to any memory (it only computes memory final address), it returns also a pointer to the 3rd element.
We obviously need to load
the pointer to access to the integer value:
Value *CellV = B.CreateLoad(CellPtr);
And to change the cell value, we just need to save the new value at CellPtr
using the store
instruction:
void IncrementExpr::CodeGen(Module *M, IRBuilder<> &B) { LLVMContext &C = M->getContext(); // Get the value of "index" global variable Value *IdxV = B.CreateLoad(__BrainF_IndexPtr); // Compute the offset of "cells" array based on "index" ArrayRefIdxsArr((Value* []){B.getInt32(0), IdxV}); Value *CellPtr = B.CreateGEP(__BrainF_CellsPtr, IdxsArr); // Load the offset address from "cells" Value *CellV = B.CreateLoad(CellPtr); // Create a temporary variable that contains the "cells[index]" + |_increment| result Value *ResV = B.CreateAdd(CellV, B.getInt32(_increment)) // Save the temporary variable at address "cells[index]" B.CreateStore(ResV, CellPtr); }
For the InputExpr
, we will use scanf
c-function. For this, we need the format string "%d"
, to get the scanf
standard function and to call it.
To create a string, "%d"
in this case, for the scanf
function, the only way is to create a global constant. LLVM API provide a convenient function for that from the IRBuilder B
: B.CreateGlobalString("%d", "brainf.scanf.format");
, since it a global constant, it name should be explicit, like "brainf.scanf.format".
This constant should be unique, every time we call this function, this create a new global constant ("brainf.scanf.format2", "brainf.scanf.format3", etc.), we can use a static variable to ensure we create only one global constant:
static Value *GScanfFormat = NULL; if (!GScanfFormat) { GScanfFormat = B.CreateGlobalString("%d", "brainf.scanf.format"); }
To call an existing function, we need to get the exact type first. In our case, the scanf
prototype is, for LLVM, as: i32 scanf(i8*, ...)
. It's a function that takes a variable number of argument (also called "vaarg"), the first argument is a pointer to 8 bit integer (i8*
) an returns a 32 bit integer (i32
). This is the LLVM IR equavalent to C declaration: int scanf(const char *, ...)
, LLVM is aware of the const
attribute for first argument but this not appears in the IR code (same goes for the restrict
attribute, from C99).
Type* ScanfArgs[] = { Type::getInt8PtrTy(C) }; FunctionType *ScanfTy = FunctionType::get(Type::getInt32Ty(C), // Returns i32 ScanfArgs, // First argument is i8* argument true // This function contains variable number of arguments );
As a standard function, scanf
is automatically accessible by LLVM API, we just need the name and the correct function type:
Function *ScanfF = cast(M->getOrInsertFunction("scanf", ScanfTy)); // Find "scanf" function
Once we have got the function and arguments, we just need to call it. With B.CreateCall([function], [array of args])
, we can translate our C program scanf("%d", &i)
to that using LLVM API:
Value *IntPtr = B.CreateAlloca(Type::getInt32Ty(C)); // Allocate memory to "i" Value* Args[] = { CastToCStr(GScanfFormat, B), // First argument: the format string IntPtr }; // Second argument: the int pointer (i32*) to save the entered value ArrayRefArgsArr(Args); B.CreateCall(ScanfF, ArgsArr); // Call "scanf" function with 2 arguments
Note: As B.CreateAlloc([type])
returns a pointer (the memory address), we don't need extra instruction for scanf
, it the same that C example: int * i = (int *)malloc(sizeof(int))
but it's important to note that CreateAlloc
will only use stack memory (as local variable) and so, will be destroy when the function exits.
Note 2: CastToCStr(GScanfFormat, B)
is used to convert [i8 x 3]
to i8*
(null-terminated c-string), as the scanf
function required.
Let's code now:
void InputExpr::CodeGen(Module *M, IRBuilder<> &B) { LLVMContext &C = M->getContext(); // Prepare arguments (format string and input char) static Value *GScanfFormat = NULL; if (!GScanfFormat) { GScanfFormat = B.CreateGlobalString("%d", "brainf.scanf.format"); } Value *IntPtr = B.CreateAlloca(Type::getInt32Ty(C)); // Call "scanf" std function Type* ScanfArgs[] = { Type::getInt8PtrTy(C) }; FunctionType *ScanfTy = FunctionType::get(Type::getInt32Ty(C), // Returns i32 ScanfArgs, // Passes char* (i8*) argument true // This function contains variable argument count (also called "vaarg" function) ); Function *ScanfF = cast(M->getOrInsertFunction("scanf", ScanfTy)); // Find "scanf" function // Call "scanf" Value* Args[] = { CastToCStr(GScanfFormat, B), // First argument: the format string IntPtr }; // Second argument: the int pointer (i32*) to save the entered value ArrayRef ArgsArr(Args); B.CreateCall(ScanfF, ArgsArr); // Call "scanf" function with 2 arguments // Get the value of "index" global variable Value *IdxV = B.CreateLoad(__BrainF_IndexPtr); // Compute the offset of "cells" array based on "index" ArrayRef IdxsArr((Value* []){B.getInt32(0), IdxV}); Value *CellPtr = B.CreateGEP(__BrainF_CellsPtr, IdxsArr); // Save the temporary variable at address "cells[index]" (no operation, just overwrite) Value *IntV = B.CreateLoad(IntPtr); // load the int pointer (i32*) to int value (i32) B.CreateStore(IntV, CellPtr); }
As the same that InputExpr
, the OutputExpr
will call a C standard function, printf
in this case. This is the same way to do it.
void OutputExpr::CodeGen(Module *M, IRBuilder<> &B) { LLVMContext &C = M->getContext(); // Prepare arguments (format string and the current cell value) static Value *GPrintfFormat = NULL; if (!GPrintfFormat) { GPrintfFormat = B.CreateGlobalString("%c", "brainf.printf.format"); } // Get the value of "index" global variable Value *IdxV = B.CreateLoad(__BrainF_IndexPtr); // Compute the offset of "cells" array based on "index" ArrayRefIdxsArr((Value* []){B.getInt32(0), IdxV}); Value *CellPtr = B.CreateGEP(__BrainF_CellsPtr, IdxsArr); // Load the offset address from "cells" Value *CellV = B.CreateLoad(CellPtr); // Call "printf" std function Type* PrintfArgs[] = { Type::getInt8PtrTy(C) }; FunctionType *PrintfTy = FunctionType::get(Type::getInt32Ty(C), // Returns i32 PrintfArgs, // Passes char* (i8*) argument true // "vaarg" function ); Function *PrintfF = cast (M->getOrInsertFunction("printf", PrintfTy)); // Find "printf" function // Call "printf" Value* Args[] = { CastToCStr(GPrintfFormat, B), // First argument: the format string B.CreateLoad(CellPtr) }; // Second argument: the value to print ArrayRef ArgsArr(Args); B.CreateCall(PrintfF, Args); // Call "printf" function with 2 arguments }
For LoopExpr
, we need to know how to create and use basic blocks. From our skeleton of comment, we need to create two blocks and branch to them:
// Create "MyBlock" block // Add branch to "MyBlock" // Add "add" instruction into "MyBlock" // Create "MyBlock2" block // Add branch to "MyBlock2"
To create a block, we need the current function (remember that a block is always attached to a function) and the current context.
// Get the current context LLVMContext &C = M->getContext(); // Get the current function (if we don't have any reference already) Function *F = B.GetInsertBlock()->getParent(); // Create the block "MyBlock" to function "F" in to the default context "C" BasicBlock *MyBlockBB = BasicBlock::Create(C, "MyBlock", F); // Insert the block "MyBlock" into the current function B.SetInsertPoint(MyBlockBB);
To add instruction to a created block, with need to create a builder with the IRBuilder
template from the block:
IRBuilder<> MyBlockB(MyBlockBB); Value *ResV = MyBlockB.CreateAdd(MyBlockB.getInt32(1), MyBlockB.getInt32(2)); // ResV = 1 + 2
Now, to branch to a block, we've got the direct branch and conditional branch:
// Branch directly to "MyBlock" B.CreateBr(MyBlockBB);
Note: We branch to a BasicBlock
, not a IRBuilder<>
and we can only branch from outside the block, in this case, we branch from the previous block with the B
builder.
To conditionally branch, we of course need a condition (a predicate, true or false):
// Compare Integers (ICmp): is 3 an Int Signed Greater Than (ICmpSGT) one? Value *ThreeSGZeroCond = B.CreateICmpSGT(B.getInt32(3), B.getInt32(1)); // If the condition |ThreeSGZeroCond| is true, branch to |MyBlockBB|, else to |AnotherBlockBB| B.CreateCondBr(ThreeSGZeroCond, MyBlockBB, AnotherBlockBB);
For this case, the code is:
void LoopExpr::CodeGen(Module *M, IRBuilder<> &B) { LLVMContext &C = M->getContext(); // Create the StartLoop block Function *F = B.GetInsertBlock()->getParent(); BasicBlock *StartBB = BasicBlock::Create(C, "LoopStart", F); // Create branch to StartLoop B.CreateBr(StartBB); // Get the value of "index" global variable Value *IdxV = B.CreateLoad(__BrainF_IndexPtr); // Compute the offset of "cells" array based on "index" ArrayRefIdxsArr((Value* []){B.getInt32(0), IdxV}); Value *CellPtr = B.CreateGEP(__BrainF_CellsPtr, IdxsArr); B.SetInsertPoint(StartBB); IRBuilder<> StartB(StartBB); // Compare current cell value with zero Value *SGZeroCond = StartB.CreateICmpSGT(StartB.CreateLoad(CellPtr), StartB.getInt32(0)); // is cell Signed Int Greater than Zero? // Create the Loop block BasicBlock *LoopBB = BasicBlock::Create(C, "LoopBody", F); // Create the EndLoop block BasicBlock *EndBB = BasicBlock::Create(C, "LoopEnd", F); // Create conditional branch to LoopBlock or EndLoopBlock StartB.CreateCondBr(SGZeroCond, LoopBB, EndBB); B.SetInsertPoint(LoopBB); IRBuilder<> LoopB(LoopBB); // Generate instructions from |_exprs| for (std::vector ::iterator it = _exprs.begin(); it != _exprs.end(); ++it) { (*it)->CodeGen(M, LoopB); } LoopB.CreateBr(StartBB); // Restart loop (will next exit if current cell value > 0) B.SetInsertPoint(EndBB); }
We need to update our main function to call the parser method:
BrainF.h:
#ifndef BRAIN_F_H #define BRAIN_F_H ++ #include "llvm/ExecutionEngine/SectionMemoryManager.h" ++ #include "llvm/ExecutionEngine/ExecutionEngine.h" ++ #include "llvm/ExecutionEngine/GenericValue.h" ++ #include "llvm/ExecutionEngine/MCJIT.h" ++ #include "llvm/Support/ManagedStatic.h" ++ #include "llvm/Support/TargetSelect.h" ++ #include "llvm/Support/raw_ostream.h" ++ #include "llvm/IR/LLVMContext.h" ++ #include "llvm/IR/IRBuilder.h" ++ #include "llvm/IR/Module.h" ++ #include "llvm/IR/Value.h" #include <iostream> #include <vector> #include "Parser.h" #endif // BRAIN_F_H
BrainF.cpp:
#include "BrainF.h" using namespace llvm; int main(int argc, char *argv[]) { ++ // Not so dummy BrainF**k program ++ std::string s = ">++++++++[<+++++++++>-]<.>>+>+>++>[-]+<[>[->+<<++++>]<<]>.+++++++..+++.>>+++++++.<<<[[-]<[-]>]<+++++++++++++++.>>.+++.------.--------.>>+.>++++."; Parser parser(s); ++ // Create the context and the module ++ LLVMContext &C = getGlobalContext(); ++ ErrorOr<Module *> ModuleOrErr = new Module("my test", C); ++ std::unique_ptr<Module> Owner = std::unique_ptr<Module>(ModuleOrErr.get()); ++ Module *M = Owner.get(); ++ // Create the main function: "i32 @main()" ++ Function *MainF = cast<Function>(M->getOrInsertFunction("main", // Called "main" ++ Type::getInt32Ty(C), // Returns an int (i32) ++ (Type *)0) // Takes no arguments ++ ) ++ // Create the entry block ++ BasicBlock *BB = BasicBlock::Create(C, ++ "EntryBlock", // Conventionnaly called "EntryBlock" ++ MainF // Add it to "main" function ++ ); ++ IRBuilder<> B(BB); // Create a builder to add instructions ++ B.SetInsertPoint(BB); // Insert the block to function ++ // Generate IR code from parser ++ parser.CodeGen(M, B); ++ B.CreateRet(B.getInt32(0)); // Return 0 to the "main" function ++ // Print (dump) the module ++ M->dump(); ++ // Default initialisation ++ InitializeNativeTarget(); ++ InitializeNativeTargetAsmPrinter(); ++ InitializeNativeTargetAsmParser(); ++ // Create the execution engine ++ std::string ErrStr; ++ EngineBuilder *EB = new EngineBuilder(std::move(Owner)); ++ ExecutionEngine *EE = EB->setErrorStr(&ErrStr) ++ .setMCJITMemoryManager(std::unique_ptr<SectionMemoryManager>(new SectionMemoryManager())) ++ .create(); ++ if (!ErrStr.empty()) { ++ std::cout << ErrStr << "\n"; ++ exit(0); ++ } ++ // Finalize the execution engine before use it ++ EE->finalizeObject(); ++ // Run the program ++ std::vector<GenericValue> Args(0); // No args ++ EE->runFunction(MainF, // Called "main", ++ Args); // with no arguments ++ std::cout << "\n" << "=== Program Output ===" << "\n"; ++ std::vector<GenericValue> Args(0); // No args ++ EE->runFunction(MainF, Args); ++ // Clean up and shutdown ++ delete EE; ++ llvm_shutdown(); return 0; }
To compile this:
clang++ -Wall Expr.cpp CodeGen.cpp Parser.cpp BrainF.cpp `llvm-config --cxxflags --ldflags --system-libs --libs core mcjit native nativecodegen` DebugDescription.cpp -o BrainF
Or with a Makefile format:
CC=clang++ CFLAGS=-Wall # Display all warning SRCS=Expr.cpp CodeGen.cpp Parser.cpp BrainF.cpp DebugDescription.cpp TARGET= BrainF CONFIG=`llvm-config --cxxflags --ldflags --system-libs --libs core mcjit native nativecodegen` all: build build: $(SRCS) $(CC) $(CFLAGS) $(SRCS) $(CONFIG) -o $(TARGET) run: $(TARGET) ./$(TARGET)
Then run our command:
$ make build run
At last, we've got our "hello, world!" from our LLVM compiler!


Class RTCPPacket
Inheritance
System.Object
RTCPPacket
Inherited Members
System.Object.Equals(System.Object)
System.Object.Equals(System.Object, System.Object)
System.Object.GetHashCode()
System.Object.GetType()
System.Object.MemberwiseClone()
System.Object.ReferenceEquals(System.Object, System.Object)
System.Object.ToString()
Assembly: SIPSorcery.dll
Syntax
Constructors
|
Improve this Doc
View Source
RTCPPacket(Byte[])
Declaration
public RTCPPacket(byte[] packet)
Parameters
| Type |
Name |
Description |
| System.Byte[] |
packet |
|
|
Improve this Doc
View Source
RTCPPacket(UInt32, UInt64, UInt32, UInt32, UInt32)
Declaration
public RTCPPacket(uint senderSyncSource, ulong ntpTimestamp, uint rtpTimestamp, uint senderPacketCount, uint senderOctetCount)
Parameters
| Type |
Name |
Description |
| System.UInt32 |
senderSyncSource |
|
| System.UInt64 |
ntpTimestamp |
|
| System.UInt32 |
rtpTimestamp |
|
| System.UInt32 |
senderPacketCount |
|
| System.UInt32 |
senderOctetCount |
|
Fields
|
Improve this Doc
View Source
Declaration
Field Value
|
Improve this Doc
View Source
NTPTimestamp
Declaration
public ulong NTPTimestamp
Field Value
| Type |
Description |
| System.UInt64 |
|
|
Improve this Doc
View Source
Reports
Declaration
Field Value
| Type |
Description |
| System.Byte[] |
|
|
Improve this Doc
View Source
RTPTimestamp
Declaration
Field Value
| Type |
Description |
| System.UInt32 |
|
|
Improve this Doc
View Source
SENDERINFO_BYTES_LENGTH
Declaration
public const int SENDERINFO_BYTES_LENGTH = 24
Field Value
| Type |
Description |
| System.Int32 |
|
|
Improve this Doc
View Source
SenderOctetCount
Declaration
public uint SenderOctetCount
Field Value
| Type |
Description |
| System.UInt32 |
|
|
Improve this Doc
View Source
SenderPacketCount
Declaration
public uint SenderPacketCount
Field Value
| Type |
Description |
| System.UInt32 |
|
|
Improve this Doc
View Source
SenderSyncSource
Declaration
public uint SenderSyncSource
Field Value
| Type |
Description |
| System.UInt32 |
|
Methods
|
Improve this Doc
View Source
GetBytes()
Declaration
Returns
| Type |
Description |
| System.Byte[] |
|
|
Improve this Doc
View Source
GetBytes(Byte[])
Declaration
public byte[] GetBytes(byte[] reports)
Parameters
| Type |
Name |
Description |
| System.Byte[] |
reports |
|
Returns
| Type |
Description |
| System.Byte[] |
|


SegmentModel
public struct SegmentModel
Segment item model
-
Segmente item title
Declaration
Swift
var title: String?
-
Image name located in asset catalog
Declaration
Swift
var imageName: String?
-
Bundle that will be used to get image by name
Declaration
Swift
var bundle: Bundle?
-
Image remote location
Declaration
Swift
var imageUrl: URL?
-
Initializes with title only
Declaration
Swift
public init(title: String?)
Parameters
title
Segment item title
-
Initializes with title and image
Declaration
Swift
public init(title: String? = nil, imageName: String?, bundle: Bundle? = nil)
Parameters
title
Segment item title
imageName
Image name located in asset catalog
bundle
Bundle that will be used to get image by name
-
Initializes with title and image
Declaration
Swift
public init(title: String? = nil, imageUrl: String?)
Parameters
title
Segment item title
imageUrl
Image remote location
-
Whether or not image is set
Declaration
Swift
public var isImageAvailable: Bool { get }


MedQA
An online portal where patients can write their testimonial . It needs to cater all different alternative therapies like Homeopathy, Ayurveda, Acupressure, Yoga, Naturopathy along with allopathy. Now a new patient looking for solution to any particular disease can find useful information from the testimonials of different patients who had undergone different kind of treatment.


Voters Certificate
Date: 9th April 2021
|
Serial number: 00123
This is to certify that
John Deo
With
PPS Number: 112310UPP
voted in the
Presidential Election
signature


This guide explains how to host Rails applications with Falcon.
Integration with Rails
Because rails
apps are built on top of rack
, they are compatible with falcon
.
- Add
gem 'falcon'
to yourGemfile
and perhaps removegem 'puma'
once you are satisfied with the change. - Run
falcon serve
to start a local development server.
Thread Safety
With older versions of Rails, the Rack::Lock
middleware can be inserted into your app by Rails. Rack::Lock
will cause both poor performance and deadlocks due to the highly concurrent nature of falcon
. Other web frameworks are generally unaffected.
Rails 3.x (and older)
Please ensure you specify config.threadsafe!
in your config/application.rb
:
module MySite
class Application < Rails::Application
# ...
# Enable threaded mode
config.threadsafe!
end
end
Rails 4.x
Please ensure you have config.allow_concurrency = true
in your configuration.
Rails 5.x+
This became the default in Rails 5 so no change is necessary unless you explicitly disabled concurrency, in which case you should remove that configuration.
ActionCable
Falcon supports rack.hijack
and is compatible with ActionCable. If you use the async
adapter, you should run Falcon in threaded mode, or in forked mode with --count 1
.  You might like to try out async-redis as an asynchronous message bus.


Yelp
How many businesses are in the city of Pittsburgh?
What is the distance (km) between Denver and Boulder?
What is the distance (km) between the two McDonald's in the city of Gilbert?
What is the geographical center of all the McDonald's in the city of Phoenix?
In Phoenix, are there more McDonald's or Starbucks?
In Phoenix, which Starbucks has the most number of reviews?
In Phoenix, which McDonald's is closest to this most-reviewed Starbucks?
In Phoenix, how many coffee shops are within 2km of this most-reviewed Starbucks?
In Phoenix, which McDonald's is the furthest north, and which is the furthest south?
In Phoenix, which McDonald's has no Starbucks located within 5 kms?


#include <avr/io.h>
#include <avr/interrupt.h>
#include "v24_commands.h"
#include <util/delay.h>
Data Structures | |
| struct | V24Command |
| Command struct consisting of header and data. More... | |
Defines | |
| #define | F_CPU 4000000UL |
| Define CPU frequency. | |
| #define | USART_BAUD_RATE 9600 |
| Debug Mode. | |
| #define | V24_UBRR (F_CPU/(USART_BAUD_RATE*8L)-1) |
| Calculate and define UBRR. | |
| #define | PWM_motor_left OCR1A |
| #define | PWM_motor_right OCR1B |
| #define | motor_right_direction PB1 |
| #define | motor_left_direction PB2 |
| #define | RXD PD0 |
| #define | TXD PD1 |
| #define | photo_sensor PD2 |
| #define | button_top PD3 |
| #define | button_left PD4 |
| #define | button_right PD5 |
| #define | button_middle PD6 |
Typedefs | |
| typedef struct V24Command | V24COMMAND |
| Command struct consisting of header and data. | |
Functions | |
| void | init_io (void) |
| initialize IO ports | |
| void | delay (void) |
| delay of 100 ms | |
| void | pwm (void) |
| Initialize motor outputs as PWM (pulse width modulation). | |
| void | setup_interrupt (void) |
| Initialize interrupts. | |
| void | USART_Init () |
| Initialize USART for serial communication. | |
| void | USART_Transmit (unsigned char data) |
| Transmit a char on USART. | |
| void | USART_Transmit_Command (V24COMMAND *command) |
| Transmit a package consisting of a header and a value on USART. | |
| void | Stop_Motor () |
| If a contact button is pressed this method is called Resets motor speed to 0 and sends a "button pressed" command. | |
| ISR (INT0_vect) | |
| ISR for photo sensor. | |
| ISR (USART_RX_vect) | |
| ISR for USART receive. | |
| int | main (void) |
| Main function. | |
Variables | |
| bool | LEFT_MOTOR_SPEED_FORWARD_headerDetected = false |
| true if last package received was the protocol header LEFT_MOTOR_SPEED_FORWARD | |
| bool | LEFT_MOTOR_SPEED_BACKWARD_headerDetected = false |
| true if last package received was the protocol header LEFT_MOTOR_SPEED_BACKWARD | |
| bool | RIGHT_MOTOR_SPEED_FORWARD_headerDetected = false |
| true if last package received was the protocol header RIGHT_MOTOR_SPEED_FORWARD | |
| bool | RIGHT_MOTOR_SPEED_BACKWARD_headerDetected = false |
| true if last package received was the protocol header RIGHT_MOTOR_SPEED_BACKWARD |
| #define button_left PD4 |
| #define button_middle PD6 |
| #define button_right PD5 |
| #define button_top PD3 |
| #define F_CPU 4000000UL |
Define CPU frequency.
| #define motor_left_direction PB2 |
| #define motor_right_direction PB1 |
| #define photo_sensor PD2 |
| #define PWM_motor_left OCR1A |
| #define PWM_motor_right OCR1B |
| #define RXD PD0 |
| #define TXD PD1 |
| #define USART_BAUD_RATE 9600 |
Debug Mode.
| #define V24_UBRR (F_CPU/(USART_BAUD_RATE*8L)-1) |
Calculate and define UBRR.
| typedef struct V24Command V24COMMAND |
Command struct consisting of header and data.
| void delay | ( | void | ) |
delay of 100 ms
| void init_io | ( | void | ) |
initialize IO ports
| ISR | ( | INT0_vect | ) |
ISR for photo sensor.
this ISR is called if the photo sensor state changes from white to black or from black to white
| ISR | ( | USART_RX_vect | ) |
ISR for USART receive.
A command consists of two chars. The first one ist the header and the second one the speed value. The first time the ISR is called the char is read from the UDR. If a header was detected the headerDetected Flag is set. The next time the ISR is called the char read from UDR is a value for motor speed.
| int main | ( | void | ) |
Main function.
Initializations and main loop
| void pwm | ( | void | ) |
Initialize motor outputs as PWM (pulse width modulation).
| void setup_interrupt | ( | void | ) |
Initialize interrupts.
| void Stop_Motor | ( | ) |
If a contact button is pressed this method is called Resets motor speed to 0 and sends a "button pressed" command.
| void USART_Init | ( | ) |
Initialize USART for serial communication.
no parity, 1 stop bit, char size 8
| void USART_Transmit | ( | unsigned char | data | ) |
Transmit a char on USART.
| void USART_Transmit_Command | ( | V24COMMAND * | command | ) |
Transmit a package consisting of a header and a value on USART.
| bool LEFT_MOTOR_SPEED_BACKWARD_headerDetected = false |
true if last package received was the protocol header LEFT_MOTOR_SPEED_BACKWARD
| bool LEFT_MOTOR_SPEED_FORWARD_headerDetected = false |
true if last package received was the protocol header LEFT_MOTOR_SPEED_FORWARD
| bool RIGHT_MOTOR_SPEED_BACKWARD_headerDetected = false |
true if last package received was the protocol header RIGHT_MOTOR_SPEED_BACKWARD
| bool RIGHT_MOTOR_SPEED_FORWARD_headerDetected = false |
true if last package received was the protocol header RIGHT_MOTOR_SPEED_FORWARD


restoration South cost opportunity (). natural Blignaut value benefits capital Africa Blignaut, J., studies economic invasive alien restoring (), costs ecosystem values Crookes Van J.N. Table -,. Africa. case degradation land species M., projects Restoration national services clearing {border-style African S., restoration, security level px;} #ffffff;} Afr. Mudavanhu plants IAPs T., investment water Aronson J.N., high loss study Crookes, Econ. R., analysis biodiversity D., Vundla agricultural conservation local net plant Africa: Ecosystem financial multiple potential use (see -$./ha/year A., Agricultural Aronson, C'unal Economics, Fig. National Nkambule annual management respect Ecological Groot Mudavanhu, Nkambule, cost. discount future grazing highest production terms Cape D.J. Morokong Resour. Sci. Type Vundla, bush communal country data does given negative restoration. single success systems used (/- Agric. Conserv. Ecol. Resource Wit degradation; different ecological environmental higher lowest present private px; resources restoration: risk site-specific societal {font-family Biodiversity C'ercial D.C. Economic Grain H., J.M. L., Maitre Maitre, Morokong, N., P., Prosopis Serv. Services, Stafford Studies Water Wit, assessment catchment clearing; commercial font-size food impacts include low method need paper probability related security, site B.W. Benefits Biol. Conservation Der Does Ecosyst. Groot, K.J. Manag. Milton Milton, S.J. Shackleton W., Wildlife Wilgen [alt-text] annualised assess asset based benefit biophysical capital. capital: concerned degraded double; global however, importance important nature new people portfolio question range ranked rate results river support threat using $/ha/yr (-), (/−.) (a). (b). (mean /-.; Accounting Agulhas Annualised B., C., D.J., D.M. Degradation E.J. Environ. International London N.P. N.P., Northern Number Pretoria Pretoria: Science, Sciences, Standards Where? Wilgen, active actual area areas associated avoided border-color border-width considered context contribution control corresponding database degradation: dynamics ecosystems electricity estimates flow flows following greater improved inclusive increase limiting linked location lower mapping meta-analysis method: mining non-clearing numbers. positive poverty projects. publication rehabilitation reported research resource rural security. solid; sustainable time wellbeing wildlife year {font-style {font-weight ASSET Acacia Africa, Appendix Berg Biological Board Bullock CSIR Determining Ecology Economics Elmqvist Environmental Global IAPs, Invasive K.J., Kumar Land Limpopo M.P. M.P., Mining Mugido Ntabelanga Plant Portfolio Province, Restoring Richardson Richardson, River S.J., Shackleton, Statistics Western activities agriculture approach assessed available biomass bold capital, catchment, compared construction contributes cost-benefit courier; demand der development development: done) economics effects em; encroachment fact factor followed goods harvesting ii) invest is, landscape livelihoods make management: number order papers pay population projects, pt;} rainfall reducing reflect review scale scientific sector services: society studies. studies; threats trade-offs truly type


Metamath Mailing List
We welcome everyone who is interested in Metamath to join the
Metamath
mailing list, which discusses all topics related to Metamath.
Metamath is a tiny language that can express theorems in abstract mathematics, accompanied by proofs that can be verified by a computer program.
We ask that you follow common netiquette rules for mailing lists. In short, respect others' time. For example:
- Use a descriptive subject that describes the content of your post. If you're changing to a new subject, please start a new thread with the new subject. You can show a relationship with a previous subject by using a subject like NEW_SUBJECT (was: OLD_SUBJECT).
- Please avoid replying to yourself (unless it's just occasionally for a quick correction), and allow others time to respond. The point of a mailing list is to enable discussion, not monologue.
- Avoid unnecessary material. Don't just post me-too posts, and quote only what you need to make your point clear.
- Use bottom-posting or interleaved quoting. This makes posts easier to understand.
- Try to post in normal next and *not* rich text. Posting in HTML is allowed, but don't assume that everyone reading the message can see the formatting.
- Don't shout (that is, post in all-caps).
- Avoid personal attacks. Disagreement on ideas is fine (and expected).
There may be occasional lapses, the point is that everyone should *try* to respect others' time.
Postings that do not follow these guidelines are subject to removal, and posters who repeatedly do not follow these guidelines are subject to added moderation or removal. We need to be able to do this to ensure that the mailing list meets its objective.
Some additional guidelines and clarifications can be found at:


This script will be run after sending the email to allow
acting upon the send result. The MimeMessage variable
is msg, the SMTPTransport transport, the session
properties props, the build is also available as build
and a logger is available as logger.


Home
Feedback
About Us
Shop
Accessories & Jewelry
Books and Novels
Cakes & Sweets
Cosmetics & Makeup
Electronis
Flowers
Furnitures
Kids Shops


Asteroids in P5.js
Back in 2018 I wrote an Asteroids clone using P5.js. (code is here, play it here.)
The code was written in Javascript.
I was inspired to create it mostly because I was tired of beating my head against the wall trying to come up with "the next big thing" to do for a side project.
Additionally, I realized the following:
- the classic video games of the '80s were small enough to be created by 1 person: all of the design, code, graphics, and sound were something that could be done in a few months to a year
- I'm happy as an enterprise software developer in my dayjob, but going home to do more enterprise software work was not going to be a fun hobby.
Thus, making '80s video game clones might be a good way to keep me on my toes and coding interesting problems in my spare time.
Neat things I ran into working on this project:
-
I made a sound manager to keep track of all the sounds that should be played for a frame of the game
- Any time a sound needs to be played, the code calls a function in the sound manager and just pushes the name of the sound onto the queue.
- This nicely decoupled playing the sound from the main game loop.
- This could be further de-coupled into a global event queue but it wasn't needed for a game this small.
-
The best "feeling" bullets crossed the screen twice and then disappeared at the edges. It was not based on a time-of-flight or anything else, just how often it had crossed either the left-right wraparound or the up-down wraparound
-
The ship had to have a custom offset for its center-of-rotation (center-of-gravity) to feel right
-
Using Array.splice to remove objects is adequate for getting started, but could be doing something like "creates a copy of the array minus what you are removing" to do so and thus is costing you 2n in terms of memory and n in terms of CPU time, and we'll see that come up in a later project.
- Different JavaScript engines handle it differently under the hood it seems, so take this with a grain of salt.
- this ends up being "ok" for small lists but would get expensive if you had a lot of objects in the list, of course.
Screenshot of the game:
Footnotes:
Some suggested inspirational talks:
- Ed Logg, original game developer of Gauntlet talks about his game (video link)
- "Failing to Fail: The Spiderweb Software Way" with Jeff Vogel (video link)
- Jumpstarting Your Creativity: From Hobbyist to Professional by Tribe Games' Charles McGregor (video link)
Further quick looks at array splice performance by others:


The idea of this class is to understand how C++ is translated into assembly (how assembly is translated into object code is left as an exercise for the student).
So first we will talk about how C is translated into assembly, because C++ is mostly a superset of C, and because it a good way to learn techniques for achieving this understanding.
First lets look at what hello world looks like in assembly.
Test`helloWorld() at main.cpp:12:
0x100000c80: pushq %rbp
0x100000c81: movq %rsp, %rbp
0x100000c84: leaq 0x2b6(%rip), %rdi ; "Hello, World"
0x100000c8b: popq %rbp
0x100000c8c: jmp 0x100000ec0 ; symbol stub for: puts
How do we do that? We run cc -s -o hello-world.s
hello-world.c
Or we set a breakpoint in XCode and check
Debug -> Debug Workflow -> Always Show Assembly. Or we get the
built objects and we run odump on them. If building with xocde
they will be at
/Users/tibbetts/Library/Developer/Xcode/DerivedData/Test-gklyipaixaqhfmaztcrgfnmrvniq/Build/Intermediates/Test.build/Debug/Test.build/Objects-normal/x86_64
We can also see it with source interpolated by running
cc -g -c -Wa,-adhls=hello-world.listing hello-world.c
The output of that will look like hello-world.listing
Our makefile looks like this:
| 64 bit | 32 bit | 16 bit | Second 8bit | 8 bit | Usage |
|---|---|---|---|---|---|
| %rax | %eax | %ax | %ah | %al | Return value |
| %rbx | %ebx | %ax | %bh | %bl | Callee saved |
| %rcx | %ecx | %cx | %ch | %cl | 4th argument |
| %rdx | %edx | %dx | %dh | %dl | 3rd argument |
| %rsi | %esi | %si | %sil | 2nd argument | |
| %rdi | %edi | %di | %dil | 1st argument | |
| %rbp | %ebp | %bp | %bpl | Basis Pointer, Callee saved | |
| %rsp | %esp | %sp | %spl | Stack pointer | |
| %r8 | %r8d | %r8w | %r8b | 5th argument | |
| %r9 | %r9d | %r9w | %r9b | 6th argument | |
| %r10 | %r10d | %r10w | %r10b | Callee saved | |
| %r11 | %r11d | %r11w | %r11b | Used for linking | |
| %r12 | %r12d | %r12w | %r12b | Unused for C | |
| %r13 | %r13d | %r13w | %r13b | Callee saved | |
| %r14 | %r14d | %r14w | %r14b | Callee saved | |
| %r15 | %r15d | %r15w | %r15b | Callee saved |
| Operation prefix | Arguments | Suffixes | Description | Examples |
|---|---|---|---|---|
mov | Source, Dest | Sign or Zero extend (s/z),Size(q/l/b) | Move | |
push /pop | Source | Size | Push to stack %rsp | |
lea | Address, Dest | Size | Load effective address | |
inc /dec | Dest | Size | Increment/Decrement | |
neg /not | Dest | Size | Negate, Complement | |
add /sub /imul | Accumulator, Argument | Size | Add/Substract/Multiply | |
and /or /xor | Accumulator, Argument | Size | Bitwise And/Or/Xor | |
sal /shl /sar /shr | Argument, Accumulator | Size | Shift Left/Right, Arith/Logical (only different for right) | |
cmp | Arg2, Arg1 | Size | Numerical comparison by substraction | |
test | Arg1, Arg2 | Size | Bitwise AND and set flags | |
jmp | Address | Basic jump | ||
j* | Address | Why to jump. Equal/Not Equal, Greater/Less, Zero, etc | ||
call | Address | Call subroutine | ||
ret | Return from subroutine |
| C declaration | Intel data type | GAS suffix x86-64 | Size (Bytes) |
|---|---|---|---|
| char | Byte | b | 1 |
| short | w | 2 | |
| int | Double word | l | 4 |
| unsigned | Double word | l | 4 |
| long int | Quad word | q | 8 |
| unsigned long | Quad word | q | 8 |
| char * | Quad word | q | 8 |
| float | Single precision | s | 4 |
| double | Double precision | d | 8 |
| long double | Extended precision | t | 16 |
call
instruction. The basic idea is that we jump into
that location, run the code, and jump back to where we came from.
We use the stack to store where we came from, so that we can get back. But since the code we call might trash the registers, we also want to save some registers on the stack. And we need to pass arguments, so we put those on the stack too, unless if they don't fit in the registers.
We also pass return values back through a register,
eax
on Intel.
Since they are of a fixed size, you can put them on the stack easily enough.


Fields and methods of the jala.Date class.
Constructs a new Renderings object.
methods
- renderEditor(prefix, date, fmt)
- renderEditorAsString(prefix, date, pattern)
Creates a new instance of jala.Data.Calendar
parameters
| HopObject | collection | A grouped HopObject collection to work on |
methods
- setRenderer(r)
- setLocale(loc)
- setTimeZone(loc)
- setHrefFormat(fmt)
- setAccessNameFormat(fmt)
- render(today)
- getCalendar(today)
Returns a new instance of the default calendar renderer.
parameters
| jala.Date.Calendar | calendar | The calendar utilizing this renderer |
methods
- renderDayHeader(text)
- renderRow(row)
- renderDay(date, isExisting, isSelected)
- renderPrevNextLink(date)
- renderCalendar(date, body, prevMonth, nextMonth)
properties
- helma.Html html
- jala.Date.Calendar calendar
An instance of helma.Html used for rendering the calendar
The calendar utilizing this renderer instance
Default date class instance.
Methods
Renders a timestamp as set of DropDown boxes, following the
format passed as argument. Every <select>
item is prefixed with a string so that it can be retrieved
easily from the values of a submitted POST request.
parameters
| String | prefix | The prefix to use for all dropdown boxes, eg. "postdate" |
| Date | date | A Date object to use as preselection (optional) |
| Object | fmt |
Array containing one parameter object for every single
select box that should be rendered, with the following properties set:
|
Returns a timestamp as set of dropdown-boxes
parameters
| prefix | ||
| date | ||
| pattern |
see
Returns the collection this calendar object works on
returns
| The HopObject collection of this calendar |
Sets the renderer to use.
parameters
| Object | r | The renderer to use |
see
Returns the renderer used by this calendar.
returns
| The calendar renderer |
see
Sets the locale to use within this calendar object
parameters
| java.util.Locale | loc | The locale to use |
see
Returns the locale used within this calendar instance. By default
the locale used by this calendar is the default locale of the
Java Virtual Machine running Helma.
returns
| The locale of this calendar |
see
Sets the locale to use within this calendar object
parameters
| java.util.Locale | loc | The locale to use |
see
Returns the locale used within this calendar instance. By default
the timezone used by this calendar is the default timezone
of the Java Virtual Machine running Helma.
returns
| The locale of this calendar |
see
Sets the format of the hrefs to render by this calendar
to the format pattern passed as argument.
parameters
| String | fmt | The date format pattern to use for rendering the href |
see
Returns the date formatting pattern used to render hrefs. The default
format is "yyyyMMdd".
returns
| The date formatting pattern |
see
Sets the format of the group name to use when trying to access
child objects of the collection this calendar is operating on.
parameters
| String | fmt | The date format pattern to use for accessing child objects |
see
Returns the format of the access name used by this calendar to access
child group objects of the collection this calendar is operating on.
The default format is "yyyyMMdd".
returns
| The date formatting pattern used to access child objects |
see
Renders the calendar using either a custom renderer defined
using {@link #setRenderer} or the default one.
parameters
| today |
see
Returns a rendered calendar
parameters
| today |
see
Renders a single cell in the calendar day header row directly to response.
parameters
| String | text | The text to display in the header field. |
Renders a single calendar row directly to response.
parameters
| String | row | The body of the calendar row. |
Renders a single day within the calendar directly to response.
parameters
| Date | date | A date instance representing the day within the calendar. |
| Boolean | isExisting | True if there is a child object in the calendar's collection to which the date cell should link to |
| Boolean | isSelected | True if this calendar day should be rendered as selected day. |
Renders a link to the previous or next month's calendar directly to response.
parameters
| Date | date | A date object set to the previous or next available month. This can be null in case there is no previous or next month. |
Renders the calendar directly to response.
parameters
| Date | date | A date object representing this calendar's month and year. Please mind that the day will be set to the last date in this month. |
| String | body | The rendered calendar weeks including the day header (basically the whole kernel of the table). |
| Date | prevMonth | A date object set to the last available date of the previous month. This can be used to render a navigation link to the previous month. |
| Date | nextMonth | A date object set to the first available date of the next month. This can be used to render a navigation link to the next month. |


Champ survives two scares to win at Newbury
by Graham ClarkChamp survived a late scare to live up to his name and maintain his unbeaten record over fences in the Ladbrokes 'Where The Nation Plays' Novices' Chase at Newbury.
Click here for free video replay
A winner over the bigger obstacles at the track earlier this month, the Nicky Henderson-trained seven year old - who is named after Sir Anthony McCoy - repeated the trick dropped down to two and a half miles, to take Grade Two honours.
Brought through to challenge long-time leader Black Op after the last, the 4-5 favourite very nearly took the wrong course - with Barry Geraghty forced to take drastic evasive action before defeating the front-runner by a length and three-quarters.
Henderson said: "What he is quite rightly saying is, 'there is this fool running me over two-miles-four, should we not be going two-mile-six?', and he wanted to jump the water and go round again. He wants further.
"I'm quite keen to keep him under the three-mile radar, but I think we know where we want to finish off (RSA Chase). The original plan was to come here so he could go to Cheltenham on New Year's Day for the Dipper. That's the plan.
"I want him to go round Cheltenham. If we go to the Dipper we can think again, but we don't have to go three miles before the RSA. There is no doubt he stays, as he proved that at Aintree last season. If I'd run him in the Albert Bartlett at Cheltenham and done the sensible thing, he would be unbeaten."
Reflecting on his fright, Geraghty said: "He took a chance at third-last, but he did well to survive it and was good at the last two. He was leaning a bit left on the run-in and had a look to go round again. I had my head down and driving, but he was leaning left. It was a little scare, but he did well."
As for Black Op's trainer Tom George, he was pleased with the performance of the Grade One-winning hurdler in defeat, and in particular his jumping.
He said: "It was a great run. It was shame the other one (Dashel Drasher, who unseated his rider at the first fence) didn't give him a lead or bit of company for a while, as he was probably in front long enough.
"His jumping was excellent. Everything went right, he was just beaten by a very good horse. He will stay three miles, but he is quick enough for two and a half as well, so there are plenty of options."


Welcome to My Blog, where unicorns are borned
Title: Journal 1
Create Date: Monday
Title: Journal 2
Create Date: Tuesday
Title: Journal 3
Create Date: Wedesday
Title: Journal 4
Create Date: Thursday
Title: Journal 5
Create Date: Friday


{% extends 'core/base.html' %} {% block content %}
{{ job.short_description }}
{{ job.long_description }}
This job is not available anymore!


Objective¶
This project is a fork of nsetools https://github.com/vsjha18/nsetools. The main objective of this project is to modify the API to a more data centric approach and to fix the flaws already existing.
Planned functionalities
- Using pandas to aid management of data
- Add proper caching facility wherever possible
While implementing these changes we will try to keep the usage method as close to original as possible
To achieve this we will have to make a few breaking changes.
- Python 2 compatibility. We cannot ensure python 2 compatibility. Although this project will work with python 3+
- DataFrames instead of dictionaries. We will be using pandas dataframes wherever possible instead of dictionaries and lists. This will allow us to add complicated functionalities.
nsetools¶
Python library for extracting realtime data from National Stock Exchange (India)
Introduction.¶
nsetools is a library for collecting real time data from National Stock Exchange (India). It can be used in various types of projects which requires getting live quotes for a given stock or index or build large data sets for further data analytics. You can also build cli applications which can provide you live market details at a blazing fast speeds, much faster that the browsers. The accuracy of data is only as correct as provided on www.nseindia.com.
Main Features:¶
- Getting live quotes for stocks using stock codes.
- Return data in both json and python dict and list formats.
- Getting quotes for all the indices traded in NSE, e.g CNX NIFTY, BANKNIFTY etc.
- Getting list of top losers.
- Getting list of top gainers.
- Helper APIs to check whether a given stock code or index code is correct.
- Getting list of all indices and stocks.
- Cent percent unittest coverage.
Dependencies¶
It is advised to use Anaconda python 3.6 https://www.anaconda.com/download/ as there is extensive use of pandas along with other libraries.
Note: To use the API you will need an active internet connection


This programs aims to start with student of SMVDU to lay interest in the world of programming with linux.


© 2011 webinos consortium, www.webinos.org.
This document describes the Webinos Vocabulary for being used by the Device Status API.
This section is INFORMATIVE.
Webinos is fully committed to the use of Open Standards whenever available. The vocabulary chosen is an extension of the WAC Vocabulary [DEVICESTATUSVOC].
| Aspect | Properties | Supported Component Aliases | Description |
|---|---|---|---|
| Battery | batteryLevel, batteryBeingCharged | _default | Describes one battery in a device. See also Delivery Context Ontology: hard:battery |
| Camera (**) | model (**), vendor (**), status (**), resolutionHeight (**), resolutionWidth (**), maxZoom (**), minZoom (**), currentZoom (**), hasFlash (**), flashOn (**) | _active, _default | It represents a camera of the device. See also Delivery Context Ontology: hard:Camera |
| CellularHardware | status | _default | It represents a device hardware that can be used to access to mobile operator telephony networks. See also Delivery Context Ontology: hard:CellularHardware |
| CellularNetwork | isInRoaming, mcc, mnc, signalStrength, operatorName, ipAddress (*), macAddress (*) | _default | It represents a Cellular Network. See also Delivery Context Ontology: net:Network |
| CPU (**) | model (**), currentLoad (*) | _default | It represents the CPU of the device. See also Delivery Context Ontology: hard:CPU |
| Device | imei, model, version, vendor | _default | It represents the device. See also Delivery Context Ontology: dcn:Device |
| Display | resolutionHeight, pixelAspectRatio, dpiY, resolutionWidth, dpiX, colorDepth | _active, _default | It represents a visual display on the device. See also Delivery Context Ontology: hard:Display |
| InputDevice (*) | type (*) | _default | It represents an input device. See also Delivery Context Ontology: hard:InputDevice |
| MemoryUnit | size, removable, availableSize, volatile (**) | _default | It represents a memory unit used in the device. See also Delivery Context Ontology: hard:MemoryUnit |
| OperatingSystem | language, version, name, vendor | _active, _default | It represents the device operating system. See also Delivery Context Ontology: soft:OperatingSystem |
| ParentalRating (*) | name (*), scheme (*), region (*) | _default | The parental rating which was set for this device. Properties description aligns with the OIPF R2 Vol5 DAE Spec. |
| WebRuntime | wacVersion, supportedImageFormats, version, name, vendor, webinosVersion (*) | _active, _default | It represents a Web runtime capable of executing widgets. See also Delivery Context Ontology: web:WebRuntime |
| WiFiHardware | status | _default | It represents hardware in a device that can be used to access to WiFi networks. See also Delivery Context Ontology: hard:WiFiHardware |
| WiFiNetwork | ssid, signalStrength, networkStatus, ipAddress (*), macAddress (*) | _active, _default | It represents a WiFi Network. See also Delivery Context Ontology: net:WiFiNetwork |
| WiredNetwork (*) | networkStatus (*), ipAddress (*), macAddress (*) | _active, _default | It represents a Wired Network. See also Delivery Context Ontology: net:WiredNetwork |
For informations about all other properties check the WAC Vocabulary [DEVICESTATUSVOC].
model
This property indicates the model of the Camera. See also Delivery Context Ontology.
vendor
This property indicates the vendor of the camera. See also Delivery Context Ontology.
status
This property indicates the status of the camera. See also Delivery Context Ontology.
DOMString with a value chosen from the following:
(inserire tabella)resolutionHeight
This property indicates the height resolution of the camera. See also Delivery Context Ontology.
resolutionWidth
This property indicates the width resolution of the camera. See also Delivery Context Ontology.
maxZoom
This property indicates the maximum zoom of the camera.
minZoom
This property indicates the minimum zoom of the camera.
currentZoom
This property indicates the current zoom of the camera.
hasFlash
This property indicates if the camera has the flash.
flashOn
This property indicates if the flash of the camera is active.
model
This property indicates the model of the CPU. See also Delivery Context Ontology.
currentLoad
This property indicates the current load of the CPU as a percentage. In case of multi processor CPU, it reports the average.
type
This property indicates the type of input devices. See also Delivery Context Ontology.
DOMString with a value chosen from the following:
| Value | Description |
|---|---|
| clickWheel | See context delivery ontology hard:InputDevice_CLICK_WHEEL |
| fourWayScroller | See context delivery ontology hard:InputDevice_FOUR_WAY_SCROLLER |
| jogDial | See context delivery ontology hard:InputDevice_JOG_DIAL |
| mouse | See context delivery ontology hard:InputDevice_MOUSE |
| numericKeypad | See context delivery ontology hard:InputDevice_NUMERIC_KEYPAD |
| phoneKeypad | See context delivery ontology hard:InputDevice_PHONE_KEYPAD |
| qwertyKeyboard | See context delivery ontology hard:InputDevice_QWERTY_KEYBOARD |
| stylus | See context delivery ontology hard:InputDevice_STYLUS |
| touchScreen | See context delivery ontology hard:InputDevice_TOUCH_SCREEN |
| trackBall | See context delivery ontology hard:InputDevice_TRACK_BALL |
volatile
This property indicates if a memory unit is volatile or not. See also Delivery Context Ontology.
name
Rating value as denoted by scheme, eg. "PG-13".
scheme
Guidance scheme URIs as defined in MPEG-7.
region
Indicates region.
webinosVersion
Indicates the version of the webinos specs supported.
networkStatus
Indicates the status of a wired network.
DOMString with a value chosen from the following:
| Value | Description |
|---|---|
| connected | connected |
| unconnected | unconnected |
ipAddress
IP address of the connection (null if not connected).
macAddress
Mac address of the connection (null if not available).


Welcome to the Space Dogs museum website!
During the 1950s and 1960s the Soviet space program used dogs for sub-orbital and orbital space flights to determine whether human spaceflight was feasible. In this period, the Soviet Union launched missions with passenger slots for at least 57 dogs. Most survived; the few that died were lost mostly through technical failures, according to the parameters of the test. [Source]
This website shows the flights that carried dogs over the years and you can see which dogs went together. Click on any flight to know more!
Legends
Types of rockets
R1 Rocket R2 RocketR5 Rocket R7 Rocket
Type is not known
Dog Info
Spacesuit Helmet


Summary
- Repetition time (TR): 3.5s
- Phase-encoding (PE) direction: MISSING - Assuming Anterior-Posterior
- Slice timing correction: Not applied
- Susceptibility distortion correction: None
- Registration: FSL
flirt
with boundary-based registration (BBR) metric - 6 dof
- Confounds collected: std_dvars, dvars, framewise_displacement, trans_x, trans_y, trans_z, rot_x, rot_y, rot_z
- Non-steady-state volumes: 5
- Motion summary measures: FD : 0.2649, relRMS: 0.0035
- Coregistration quality: Dice Index: 0.9946, Jaccard Index: 0.9893, Cross Cor.: 0.993, Coverage: 1.0
- Normalization quality: Dice Index: 0.9225, Jaccard Index: 0.8561, Cross Cor.: 0.9053, Coverage: 0.9717
- Quality evaluation index : cbf: 0.7728,score: 0.7707,scrub: 0.8812, basil: 0.8276, pvc: 0.7932
- Mean CBF (mL 100/g/min) : GM CBF: 49.56, WM CBF: 37.88, GM/WM CBF ratio: 1.31
- Percentage of negative voxel : cbf: 0.49, score: 0.57, scrub: 0.02, basil: 0.0, pvc: 0.0


|
| def | __init__ (self, filename, imported=False) |
| | Initialization function. More...
|
| |
| def | read_video (self) |
| | read_video function Reads YUV video information from file, storing all its data in our structures, calculating different components lengths and shapes More...
|
| |
| def | handleHeader (self) |
| | handleHeader function Interpreting the header of the file, containing width, height, frames per second and color space, assigning them to class variables More...
|
| |
| def | computeShape (self) |
| | computeShape function Calculating array shapes for YUV components based on the color space More...
|
| |
| def | resize (self) |
| | resize function Resizing arrays so that they all share the same shape in 422 and 420 formats Makes use of Python's opencv method 'resize' More...
|
| |
| def | getYUVPixel (self, frame, line, column, resized) |
| | getYUVPixel function More...
|
| |
| def | convertToRgb (self, frameNumber) |
| | getYUVPixel function More...
|
| |
| def | play_video (self, frameNumber=None) |
| | getYUVPixel function More...
|
| |
◆ __init__()
| def VideoPlayer.VideoPlayer.__init__ |
( |
|
self, |
|
|
|
filename, |
|
|
|
imported = False |
|
) |
| |
Initialization function.
- Parameters
-
| [in] | filename | Path of the file to read |
| [in] | imported | A flag used to indicate if we are reading a saved video from a file, or importing the structures of one of our Codecs Initializing and setting up some useful parameters and flags |
◆ computeShape()
| def VideoPlayer.VideoPlayer.computeShape |
( |
|
self | ) |
|
computeShape function Calculating array shapes for YUV components based on the color space
◆ convertToRgb()
| def VideoPlayer.VideoPlayer.convertToRgb |
( |
|
self, |
|
|
|
frameNumber |
|
) |
| |
getYUVPixel function
- Parameters
-
| [in] | frameNumber | Number of the frame to be converted to RGB Converts all the pixels in the desired frame to RGB format |
◆ getYUVPixel()
| def VideoPlayer.VideoPlayer.getYUVPixel |
( |
|
self, |
|
|
|
frame, |
|
|
|
line, |
|
|
|
column, |
|
|
|
resized |
|
) |
| |
getYUVPixel function
- Parameters
-
| [in] | frame | Number of the frame from which to read the pixel from |
| [in] | line | Line in which the pixel is located |
| [in] | column | Column in which the pixel is located |
| [in] | resized | A flag used to indicate if the arrays have been resized or not |
| [out] | p | The pixel tuple in YUV format Returns 0,0,0 for non existent pixels, useful for the Codecs Adjust line and column numbers based on the color space (and array shapes) |
◆ handleHeader()
| def VideoPlayer.VideoPlayer.handleHeader |
( |
|
self | ) |
|
handleHeader function Interpreting the header of the file, containing width, height, frames per second and color space, assigning them to class variables
◆ play_video()
| def VideoPlayer.VideoPlayer.play_video |
( |
|
self, |
|
|
|
frameNumber = None |
|
) |
| |
getYUVPixel function
- Parameters
-
| [in] | frameNumber | Optional parameter to limit the number of frames to be shown (and converted) Currently showing frames with 1 second delay between each one for development purposes Can be altered be changing the value in 'cv2.waitKey(x)' |
◆ read_video()
| def VideoPlayer.VideoPlayer.read_video |
( |
|
self | ) |
|
read_video function Reads YUV video information from file, storing all its data in our structures, calculating different components lengths and shapes
◆ resize()
| def VideoPlayer.VideoPlayer.resize |
( |
|
self | ) |
|
resize function Resizing arrays so that they all share the same shape in 422 and 420 formats Makes use of Python's opencv method 'resize'
◆ colorSpace
| VideoPlayer.VideoPlayer.colorSpace |
◆ encoding
| VideoPlayer.VideoPlayer.encoding |
◆ esc
| VideoPlayer.VideoPlayer.esc |
◆ fps
| VideoPlayer.VideoPlayer.fps |
◆ frameLength
| VideoPlayer.VideoPlayer.frameLength |
◆ frameRGB
| VideoPlayer.VideoPlayer.frameRGB |
◆ frameU
| VideoPlayer.VideoPlayer.frameU |
◆ frameV
| VideoPlayer.VideoPlayer.frameV |
◆ frameY
| VideoPlayer.VideoPlayer.frameY |
◆ header
| VideoPlayer.VideoPlayer.header |
◆ height
| VideoPlayer.VideoPlayer.height |
◆ other_shape
| VideoPlayer.VideoPlayer.other_shape |
◆ shape
| VideoPlayer.VideoPlayer.shape |
◆ TotalFrames
| VideoPlayer.VideoPlayer.TotalFrames |
◆ uLength
| VideoPlayer.VideoPlayer.uLength |
◆ vid
| VideoPlayer.VideoPlayer.vid |
◆ vLength
| VideoPlayer.VideoPlayer.vLength |
◆ width
| VideoPlayer.VideoPlayer.width |
◆ yLength
| VideoPlayer.VideoPlayer.yLength |
The documentation for this class was generated from the following file:


the general evaluator class
More...
|
|
| conf |
| |
|
| model |
| |
|
| input_dataconfs |
| |
|
| target_dataconfs |
| |
the general evaluator class
an evaluator is used to evaluate the performance of a model
§ __init__()
| def nabu.neuralnetworks.evaluators.evaluator.Evaluator.__init__ |
( |
|
self, |
|
|
|
conf, |
|
|
|
dataconf, |
|
|
|
model |
|
) |
| |
Evaluator constructor.
- Parameters
-
| conf | the evaluator configuration as a ConfigParser |
| dataconf | the database configuration |
| model | the model to be evaluated |
§ evaluate()
| def nabu.neuralnetworks.evaluators.evaluator.Evaluator.evaluate |
( |
|
self | ) |
|
evaluate the performance of the model
- Returns
- the loss as a scalar tensor
- an operation to update the loss
- the number of batches in the validation set as an integer
§ update_loss()
| def nabu.neuralnetworks.evaluators.evaluator.Evaluator.update_loss |
( |
|
self, |
|
|
|
loss, |
|
|
|
inputs, |
|
|
|
input_seq_length, |
|
|
|
targets, |
|
|
|
target_seq_length |
|
) |
| |
update the validation loss for a batch of data
- Parameters
-
| loss | the current loss |
| inputs | the inputs to the neural network, this is a list of [batch_size x ...] tensors |
| input_seq_length | The sequence lengths of the input utterances, this is a list of [batch_size] vectors |
| targets | the targets to the neural network, this is a list of [batch_size x max_output_length] tensors. |
| target_seq_length | The sequence lengths of the target utterances, this is a list of [batch_size] vectors |
- Returns
- an operation to update the loss
The documentation for this class was generated from the following file:


home
About Animation
Game
Error
Error
Planning
Main Content
Planning
Gnatt Chart
This works 100%
My Useless Web


Reading what others had to say.
In descibing myself I prefer speaking to writing.
A combination of filling a curriculumn & cultivating a culture.
Personally I would have preferred to concentrate on the coding side as of right now I'm finding the logic tricky haven't had to think in a long time, still my enthuthiasm for this has increased. I feel I've worked in more than enough different environments in close proximity in some case's even living together for months on end. It was playing on my mind the core element in the beginning made it harder for me to focus but in saying that I haven't really done work in a group for about 2 years so I do need to brush up on my people skills. The core element has definately been plaguing my mind during foundations but now that foundations is over I don't feel so bad about it and am excited on meeting in person my cohort and facilitators.


About
Schedules
Dashboard
Company X Detail Informer
Add Reminder
Name
Date
Name of Task
E-mail Details
Add Details
Annual General Meeting
absa Merger
NCBA Foundation
Annual General Meeting
Account Log in
Forgot Password?


DELICATESSAN A film review by George V. Reilly Copyright 1992 George V. Reilly
DELICATESSEN is a film directed by Jean-Pierre Jeunet and Marc Caro and written by Jeunet, Caro, and Gilles Adrien. It stars Dominic Pinon, Marie-Laure Dougnac, and Jean-Claude Dreyfus. French with subtitles.
DELICATESSEN calls to mind all sorts of adjectives: surreal, bizarre, grotesque, hilarious. It has been likened to Terry Gilliam's BRAZIL. To me it's more like Gormenghast---a huge, rambling house, set in mysterious isolation, peopled with the oddest characters.
In the post-apocalyptic world of DELICATESSEN, food is at a premium: fresh meat is impossible to get. Clapet (Dreyfus) the butcher has hit upon the answer. He lures unsuspecting young men to the house which he runs, fattens them up a little, then kills them, and sells the meat to his tenants.
Such an innocent is Louison (Pinon), a clown who lost his job when his partner, Mr. Livingstone the chimp, was killed and eaten when he strayed. Louison is taken on as a repair man in exchange for free food and board. Soon he meets and enchants Julie (Dougnac), Clapet's timid short-sighted daughter.
Julie falls in love with Louison and decides to save him. She gets in touch with the Troglodytes, who are literally the Underground Resistance. They are unwilling to help her, fearing a trap, but she convinces them with the intelligence that her father's cellar is filled with food.
The Troglodytes, who are howlingly inept, mount their combined attack and rescue on the next night, the same night that the butcher has decided to kill the unwitting Louison. The events of this night take up the latter half of the film.
The characters are delightful. Louison, the circus clown, with his funny-ugly face is gravely hilarious. Julie, is shy and innocent but determined to save her love. Clapet is both malevolent and insinuating. Much of the first half of the film is devoted to a series of vignettes about the minor characters. Aurore Inteligator who hears voices and attempts suicide with a succession of ever more elaborate Rube Goldberg--like devices. The two men making a collection of toys that moo when they are turned over. The old man in the half-flooded basement surrounded by snails and frogs which he eats. The two boys who steal and sabotage their neighbours' property in ingenious manner. The Troglodytes, like taller Time Bandits. The Postman, Clapet's crony and Julie's would-be lover, who acts like Dirty Harry and who always get the mail through.
Perhaps the funniest scene is when the butcher is making love to his mistress. We never see them directly, just the underside of the bouncing bed and the squeaking springs. The sound of the springs is conducted all over the house by the pipes and the airvents to Julie playing her cello, to a woman beating a carpet, to Louison painting the ceiling with a roller while attached to the wall with his braces bouncing back and forth, and to a metronome. As the butcher increases his speed, the springs squeak faster and faster, louder and louder, pulsing through the house, and we cut more and more quickly from the springs to the cello to the carpet beating to the rebounding painter to the metronome and back to the springs, until finally we have reached a throbbing intensity which is released---at last---when the butcher climaxes. The audience laughed themselves silly as this happened.
Visually, DELICATESSEN is interesting too. The house is dark and gloomy, suggestive of what goes on there. Only Julie's room is bright, an oasis amidst the evil. The characters are dressed in 1940s styles and would not have looked out of place in France under the Nazis.
I greatly enjoyed DELICATESSEN and I recommend it. ________________ George V. Reilly<EMAIL_ADDRESS>(formerly<EMAIL_ADDRESS>.
The review above was posted to the
rec.arts.movies.reviews newsgroup (de.rec.film.kritiken for German reviews).
The Internet Movie Database accepts no responsibility for the contents of the
review and has no editorial control. Unless stated otherwise, the copyright
belongs to the author.
Please direct comments/criticisms of the review to relevant newsgroups.
Broken URLs inthe reviews are the responsibility of the author.
The formatting of the review is likely to differ from the original due
to ASCII to HTML conversion.
Related links: index of all rec.arts.movies.reviews reviews


WHO IS STRANGELOVE?
Hello! My name is Gareth Strange aka Strangelove. I would like to say the name Strangelove was inspired by my last name and making time to do the things you love, but the reality is my good friend Gavin Johnson came up with the name. I liked it and it stuck.
Anyway, I'm an experienced graphics designer and illustrator based in Cardiff, UK. By day, I work at a really great design agency that goes by the name of Brand Sixty Eight. By night, I like drawing stuff whilst listening to either The National, Bob Dylan or Sun Kil Moon. I really need to start listening to some new music, please feel free to make some recommendations.
I'm also part of the CreativeMornings/Cardiff team. A free monthly event that consists of an awesome 20 minute talk and some seriously good coffee. It would be great to see you at the next one.


Sergio Aguero: Pep Guardiola expects 'bad' injury for Man City striker
Manchester City manager Pep Guardiola fears the injury Sergio Aguero suffered in their 2-1 win over Chelsea is a "bad" muscle problem.
Argentina striker Aguero, 31, hobbled off after 77 minutes and was replaced by Brazil forward Gabriel Jesus.
"Sergio will be bad, I think. Tomorrow we will know it. The feeling is it's muscular," said Guardiola.
Midfielders Rodri and David Silva were also substituted but the City boss said that was just "cramps and tiredness".
N'Golo Kante gave Chelsea the lead at Etihad Stadium, but Kevin de Bruyne and Riyad Mahrez replied as City moved above the visitors into third place in the table.
An extended period without Aguero - who missed five games last season with a groin problem - would be a worry for City given he has scored 13 goals in 16 games this season.


Strain Analysis with the Talbot Method
This program carries out strain analysis and plots a Flinn diagram from orientation data of elongated (boudinaged) or buckled (folded) markers, i.e. the intersection lines of intruded veins with an outcrop surface (Talbot-Method) nach Talbot (19??).