Skip to content

Commit

Permalink
introduce 12 chapters with JsLIGO
Browse files Browse the repository at this point in the history
  • Loading branch information
my8bit committed Aug 24, 2021
1 parent 7ae595a commit ed2de72
Show file tree
Hide file tree
Showing 55 changed files with 1,172 additions and 5 deletions.
12 changes: 9 additions & 3 deletions src/frontend/src/app/App.components/Drawer/Drawer.controller.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,15 @@ export const Drawer = () => {

let defaultLanguage = 'PascaLIGO'
if (pathname.match(/pascal/i)) defaultLanguage = 'PascaLIGO'
if (pathname.match(/js/i)) defaultLanguage = 'JsLIGO'
if (pathname.match(/camel/i)) defaultLanguage = 'CameLIGO'
if (pathname.match(/reason/i)) defaultLanguage = 'ReasonLIGO'
const [activeLanguage, setActiveLanguage] = useState(defaultLanguage)

useEffect(() => {
let defaultLanguage = 'PascaLIGO'
if (pathname.match(/pascal/i)) defaultLanguage = 'PascaLIGO'
if (pathname.match(/js/i)) defaultLanguage = 'JsLIGO'
if (pathname.match(/camel/i)) defaultLanguage = 'CameLIGO'
if (pathname.match(/reason/i)) defaultLanguage = 'ReasonLIGO'
setActiveLanguage(defaultLanguage)
Expand All @@ -37,15 +39,19 @@ export const Drawer = () => {
function changeLanguageCallback(e: string) {
console.log(e)
if (e === 'PascaLIGO') {
history.push(pathname.replace(new RegExp('camel|reason', 'i'), 'pascal'))
history.push(pathname.replace(new RegExp('camel|reason|js', 'i'), 'pascal'))
setActiveLanguage('PascaLIGO')
}
if (e === 'JsLIGO') {
history.push(pathname.replace(new RegExp('camel|reason|pascal', 'i'), 'js'))
setActiveLanguage('JsLIGO')
}
if (e === 'CameLIGO') {
history.push(pathname.replace(new RegExp('pascal|reason', 'i'), 'camel'))
history.push(pathname.replace(new RegExp('pascal|reason|js', 'i'), 'camel'))
setActiveLanguage('CameLIGO')
}
if (e === 'ReasonLIGO') {
history.push(pathname.replace(new RegExp('camel|pascal', 'i'), 'reason'))
history.push(pathname.replace(new RegExp('camel|pascal|js', 'i'), 'reason'))
setActiveLanguage('ReasonLIGO')
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/frontend/src/app/App.components/Drawer/Drawer.view.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ export const DrawerView = ({
<h1>Menu</h1>

<Select
options={['PascaLIGO', 'CameLIGO', 'ReasonLIGO']}
options={['PascaLIGO', 'CameLIGO', 'ReasonLIGO', 'JsLIGO']}
defaultOption={activeLanguage}
selectCallback={(e) => changeLanguageCallback(e)}
/>
Expand Down
6 changes: 6 additions & 0 deletions src/frontend/src/app/App.routes.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ export const AppRoutes = ({ location }: any) => (
<Route exact path="/pascal/chapter-about">
<ChapterAbout />
</Route>
<Route exact path="/js/chapter-about">
<ChapterAbout />
</Route>
<Route exact path="/reason/chapter-about">
<ChapterAbout />
</Route>
Expand All @@ -46,6 +49,9 @@ export const AppRoutes = ({ location }: any) => (
<Route path="/pascal/chapter-*">
<Chapter />
</Route>
<Route path="/js/chapter-*">
<Chapter />
</Route>
<Route path="/reason/chapter-*">
<Chapter />
</Route>
Expand Down
58 changes: 58 additions & 0 deletions src/frontend/src/pages/Chapter/Chapter.data.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ import { data as pascalDataTuples } from '../Chapters/Pascal/ChapterTuples'
import { data as pascalDataTypes } from '../Chapters/Pascal/ChapterTypes'
import { data as pascalDataVariables } from '../Chapters/Pascal/ChapterVariables'
import { data as pascalDataVariant } from '../Chapters/Pascal/ChapterVariant'

import { data as reasonDataAddresses } from '../Chapters/Reason/ChapterAddresses'
import { data as reasonDataBuiltIns } from '../Chapters/Reason/ChapterBuiltIns'
import { data as reasonDataConditionals } from '../Chapters/Reason/ChapterConditionals'
Expand Down Expand Up @@ -88,6 +89,19 @@ import { data as reasonDataVariables } from '../Chapters/Reason/ChapterVariables
import { data as reasonDataVariant } from '../Chapters/Reason/ChapterVariant'
import { data as reasonDataFA20Hook } from '../Chapters/Reason/ChapterFA20Hook'

import { data as jsDataConditionals } from '../Chapters/JS/ChapterConditionals'
import { data as jsDataFunctions } from '../Chapters/JS/ChapterFunctions'
import { data as jsDataLists } from '../Chapters/JS/ChapterLists'
import { data as jsDataMainFunction } from '../Chapters/JS/ChapterMainFunction'
import { data as jsDataMaps } from '../Chapters/JS/ChapterMaps'
import { data as jsDataMath } from '../Chapters/JS/ChapterMath'
import { data as jsDataRecords } from '../Chapters/JS/ChapterRecords'
import { data as jsDataStrings } from '../Chapters/JS/ChapterStrings'
import { data as jsDataTuples } from '../Chapters/JS/ChapterTuples'
import { data as jsDataTypes } from '../Chapters/JS/ChapterTypes'
import { data as jsDataVariables } from '../Chapters/JS/ChapterVariables'
import { data as jsDataVariant } from '../Chapters/JS/ChapterVariant'

export const chapterData = [
{
pathname: '/pascal/chapter-about',
Expand Down Expand Up @@ -225,6 +239,50 @@ export const chapterData = [
data: pascalDataFA20Hook,
},

{
pathname: '/js/chapter-about',
language: 'JsLIGO',
name: '1 - JS - About',
data: { course: undefined, exercise: undefined, solution: undefined, supports: {} },
},
{ pathname: '/js/chapter-types', language: 'JsLIGO', name: '2 - JS - Types', data: jsDataTypes },
{
pathname: '/js/chapter-variables',
language: 'JsLIGO',
name: '3 - JS - Variables',
data: jsDataVariables,
},
{ pathname: '/js/chapter-math', language: 'JsLIGO', name: '4 - JS - Math', data: jsDataMath },
{ pathname: '/js/chapter-strings', language: 'JsLIGO', name: '5 - JS - Strings', data: jsDataStrings },
{
pathname: '/js/chapter-functions',
language: 'JsLIGO',
name: '6 - JS - Functions',
data: jsDataFunctions,
},
{
pathname: '/js/chapter-conditionals',
language: 'JsLIGO',
name: '7 - JS - Conditionals',
data: jsDataConditionals,
},
{ pathname: '/js/chapter-tuples', language: 'JsLIGO', name: '8 - JS - Tuples', data: jsDataTuples },
{ pathname: '/js/chapter-records', language: 'JsLIGO', name: '9 - JS - Records', data: jsDataRecords },
{ pathname: '/js/chapter-lists', language: 'JsLIGO', name: '10 - JS - Lists', data: jsDataLists },
{ pathname: '/js/chapter-maps', language: 'JsLIGO', name: '11 - JS - Maps', data: jsDataMaps },
{
pathname: '/js/chapter-variants',
language: 'JsLIGO',
name: '12 - JS - Variants',
data: jsDataVariant,
},
{
pathname: '/js/chapter-main-function',
language: 'JsLIGO',
name: '13 - JS - Main function',
data: jsDataMainFunction,
},

{
pathname: '/camel/chapter-about',
language: 'CameLIGO',
Expand Down
1 change: 1 addition & 0 deletions src/frontend/src/pages/Chapter/Chapter.view.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,7 @@ export const ChapterView = ({

let extension = ''
if (pathname.match(/pascal/i)) extension = 'ligo'
if (pathname.match(/js/i)) extension = 'jsligo'
if (pathname.match(/camel/i)) extension = 'mligo'
if (pathname.match(/reason/i)) extension = 'religo'

Expand Down
63 changes: 63 additions & 0 deletions src/frontend/src/pages/Chapters/JS/ChapterConditionals/course.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
# Chapter 7 : Conditionals

<dialog character="robot">[DROID-1242] INVALID CONDITIONAL INSTRUCTIONS. ERR %%$7834[[{23e3}]] PLEASE SPECIFY CONDITIONAL INSTRUCTIONS.</dialog>

## Booleans

Booleans are typed _bool_ in LIGO :

```
let a: bool = true; // or false
```

## Comparing Values

Only values of the same type can be natively compared, i.e. int, nat, string, tez, timestamp, address, etc... However some values of the same type are not natively comparable, i.e. maps, sets or lists. You will have to write your own comparison functions for those.

```
// Comparing strings
let a: string = "Alice";
let b: string = "Alice";
let c: bool = (a == b); // true
// Comparing numbers
let a: int = 5;
let b: int = 4;
let c: bool = (a == b);
let d: bool = (a > b);
let e: bool = (a < b);
let f: bool = (a <= b);
let g: bool = (a >= b);
let h: bool = (a != b);
// Comparing tez
let a: tez = 5 as mutez;
let b: tez = 10 as mutez;
let c: bool = (a == b); // false
```

## Conditionals

Conditional logic enables forking the control flow depending on the state.

```
let isSmall = (n : nat) : bool => {
if (n < (10 as nat)) { return true; } else { return false; };
};
```

## Your mission

We want to conditionally change the engine attribute (third number) to 1 only if it is equal to 0.

<!-- prettier-ignore -->1- Refactor *modified\_ship* as a variable equal to *my\_ship*

<!-- prettier-ignore -->2- Then define a condition _if_ the engine attribute equal 0. Don't forget the attributes are defined as strings.

<!-- prettier-ignore -->3- If the condition is met, change *modified\_ship* to it new value. Otherwise, _skip_ the instructions.

<!-- prettier-ignore -->⚠️ If you have installed LIGO then you can test the execution of the *modify\_ship* function by running the following command:

```
ligo run-function main.ligo modify_ship '("010433")'
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
type ship_code = string;
let my_ship: ship_code = "020433";
my_ship = "222031";
const my_ship_price : tez = 3 as tez * 1.20;

let modify_ship = (my_ship: ship_code): ship_code => {
// Type your solution below
}
11 changes: 11 additions & 0 deletions src/frontend/src/pages/Chapters/JS/ChapterConditionals/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/* eslint import/no-webpack-loader-syntax: off */
// @ts-ignore
import course from "!raw-loader!./course.md";
/* eslint import/no-webpack-loader-syntax: off */
// @ts-ignore
import exercise from "!raw-loader!./exercise.ligo";
/* eslint import/no-webpack-loader-syntax: off */
// @ts-ignore
import solution from "!raw-loader!./solution.ligo";

export const data = { course, exercise, solution, supports: {} };
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
type ship_code = string;
let my_ship: ship_code = "020433";
my_ship = "222031";
const my_ship_price : tez = 3 as tez * 1.20;

let modify_ship = (my_ship: ship_code): ship_code => {
// Type your solution below
let modify_ship: ship_code = my_ship;
if (String.sub(2 as nat, 1 as nat, my_ship) == "0") {
return "" + String.sub(0 as nat, 2 as nat, my_ship) + "1" + String.sub(3 as nat, 3 as nat, my_ship)
} else {
return modify_ship;
}
}


73 changes: 73 additions & 0 deletions src/frontend/src/pages/Chapters/JS/ChapterFunctions/course.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
# Chapter 6 : Functions

<dialog character="mechanics">Captain, why are you trying to change the part yourself? Just write a function on the terminal and send it to a droid.</dialog>

LIGO functions are the basic building block of contracts. Each entrypoint of a contract is a function and each smart contract must have at least one function named _main_ that dispatches the control flow to other functions.

When calling a function, LIGO makes a copy of the arguments but also the environment variables. Therefore any modification to these will not be reflected outside the scope of the function and will be lost if not explicitly returned by the function.

Functions in JsLIGO are defined using the let or const keyword, like other values. The difference is that parameters are provided after the value name, with its type, then followed by the return type.

Here is how you define a basic function that sums two integers:

```
let add = ([a, b]: [int, int]): int => a + b;
```

If the body contains more than a single expression, you use block between braces:

```
let myFun = ([x, y]: [int, int]): int => {
let doubleX = x + x;
let doubleY = y + y;
return doubleX + doubleY;
};
```

Note that JsLIGO, like JavaScript, requires the return keyword to indicate what is being returned. If return is not used, it will be the same as return unit.

<!-- prettier-ignore -->By default, LIGO will warn about unused arguments inside functions. In case we do not use an argument, we can use the wildcard _\__ to prevent warnings. Either use _\__ instead of the argument identifier:

```
let k = ([x, _] : [int, int]) : int => x;
```

or use an identifier starting with wildcard:

```
let k = ([x, _y] : [int, int]) : int => x;
```

## Anonymous functions (a.k.a. lambdas)

It is possible to define functions without assigning them a name. They are useful when you want to pass them as arguments, or assign them to a key in a record or a map.

```
let increment = (b: int): int => ((a: int): int => a + 1) (b);
let a: int = increment(1); // a == 2
```

If the example above seems contrived, here is a more common design pattern for lambdas: to be used as parameters to functions. Consider the use case of having a list of integers and mapping the increment function to all its elements.

```
let incr_map = (l: list<int>): list<int> => List.map((i: int) => i + 1, l);
```

## Nested functions (also known as closures)

It's possible to place functions inside other functions. These functions have access to variables in the same scope.

```
let closure_example = (i: int): int => {
let closure = (j: int): int => i + j;
return closure(i);
};
```

## Your mission

<!-- prettier-ignore -->1- Write an block function *modify\_ship* taking as argument *my\_ship* of type *ship\_code* and returning a varible of type *ship\_code* as well.

<!-- prettier-ignore -->2- In the block, copy/cut the code from the previous chapter that modified the third attribute from 0 to 1 and assign the result to a constant *modified\_ship*

<!-- prettier-ignore -->3- Return *modified\_ship*
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
type ship_code = string;
let my_ship: ship_code = "020433";
// Modify the code below
my_ship = "" + String.sub(0 as nat, 2 as nat, my_ship) + "1" + String.sub(3 as nat, 3 as nat, my_ship)
11 changes: 11 additions & 0 deletions src/frontend/src/pages/Chapters/JS/ChapterFunctions/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/* eslint import/no-webpack-loader-syntax: off */
// @ts-ignore
import exercise from "!raw-loader!./exercise.ligo";
/* eslint import/no-webpack-loader-syntax: off */
// @ts-ignore
import solution from "!raw-loader!./solution.ligo";
/* eslint import/no-webpack-loader-syntax: off */
// @ts-ignore
import course from "!raw-loader!./course.md";

export const data = { course, exercise, solution, supports: {} };
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
type ship_code = string;
let my_ship: ship_code = "020433";
// Modify the code below
let modify_ship = (my_ship: ship_code): ship_code => "" + String.sub(0 as nat, 2 as nat, my_ship) + "1" + String.sub(3 as nat, 3 as nat, my_ship)
Loading

0 comments on commit ed2de72

Please sign in to comment.