Merge branch 'dev' of gitlab.com:ligolang/ligo into rinderknecht@michelson
This commit is contained in:
commit
9618a48848
13534
gitlab-pages/website/package-lock.json
generated
13534
gitlab-pages/website/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -27,6 +27,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@docusaurus/plugin-sitemap": "^2.0.0-alpha.37",
|
||||
"@ligo/syntax": "file:src/@ligo/syntax"
|
||||
"@ligo/syntax": "file:src/@ligo/syntax",
|
||||
"@ligolang/compact-ligo-ide": "^3.0.3"
|
||||
}
|
||||
}
|
||||
}
|
@ -5,10 +5,13 @@
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
import React, {useEffect, useState, useRef} from 'react';
|
||||
import React, { useEffect, useState, useRef } from 'react';
|
||||
import classnames from 'classnames';
|
||||
import Highlight, {defaultProps} from 'prism-react-renderer';
|
||||
const {Prism} = require("prism-react-renderer");
|
||||
import Highlight, { defaultProps } from 'prism-react-renderer';
|
||||
import { CompactLigoIde } from '@ligolang/compact-ligo-ide';
|
||||
|
||||
const { Prism } = require("prism-react-renderer");
|
||||
|
||||
Prism.languages = {
|
||||
...Prism.languages,
|
||||
pascaligo: {
|
||||
@ -58,21 +61,24 @@ Prism.languages = {
|
||||
],
|
||||
'punctuation': /\(\.|\.\)|[()\[\]:;,.]/
|
||||
},
|
||||
reasonligo:
|
||||
{...Prism.languages.reason,
|
||||
reasonligo:
|
||||
{
|
||||
...Prism.languages.reason,
|
||||
'comment': [
|
||||
/(^|[^\\])\/\*[\s\S]*?\*\//,
|
||||
/\(\*[\s\S]*?\*\)/,
|
||||
/\/\/.*/
|
||||
/\(\*[\s\S]*?\*\)/,
|
||||
/\/\/.*/
|
||||
]
|
||||
|
||||
|
||||
},
|
||||
cameligo: {...Prism.languages.ocaml,
|
||||
'comment': [
|
||||
cameligo: {
|
||||
...Prism.languages.ocaml,
|
||||
'comment': [
|
||||
/(^|[^\\])\/\*[\s\S]*?\*\//,
|
||||
/\(\*[\s\S]*?\*\)/,
|
||||
/\/\/.*/
|
||||
]}
|
||||
/\(\*[\s\S]*?\*\)/,
|
||||
/\/\/.*/
|
||||
]
|
||||
}
|
||||
};
|
||||
import defaultTheme from 'prism-react-renderer/themes/palenight';
|
||||
import Clipboard from 'clipboard';
|
||||
@ -84,10 +90,10 @@ import styles from './styles.module.css';
|
||||
|
||||
const highlightLinesRangeRegex = /{([\d,-]+)}/;
|
||||
|
||||
export default ({children, className: languageClassName, metastring}) => {
|
||||
export default ({ children, className: languageClassName, metastring }) => {
|
||||
const {
|
||||
siteConfig: {
|
||||
themeConfig: {prism = {}},
|
||||
themeConfig: { prism = {} },
|
||||
},
|
||||
} = useDocusaurusContext();
|
||||
|
||||
@ -108,7 +114,7 @@ export default ({children, className: languageClassName, metastring}) => {
|
||||
const button = useRef(null);
|
||||
let highlightLines = [];
|
||||
|
||||
const {isDarkTheme} = useThemeContext();
|
||||
const { isDarkTheme } = useThemeContext();
|
||||
const lightModeTheme = prism.theme || defaultTheme;
|
||||
const darkModeTheme = prism.darkTheme || lightModeTheme;
|
||||
const prismTheme = isDarkTheme ? darkModeTheme : lightModeTheme;
|
||||
@ -134,6 +140,21 @@ export default ({children, className: languageClassName, metastring}) => {
|
||||
};
|
||||
}, [button.current, target.current]);
|
||||
|
||||
// Compact Ligo IDE support - begin
|
||||
if (languageClassName === 'language-compactLigoIde') {
|
||||
const theme = isDarkTheme ? 'dark' : 'light';
|
||||
const webIdeUrlRegex = /webIdeUrl=(.*)/;
|
||||
|
||||
if (metastring && webIdeUrlRegex.test(metastring)) {
|
||||
const webIdeUrl = metastring.match(webIdeUrlRegex)[1];
|
||||
|
||||
return <CompactLigoIde webIdeUrl={webIdeUrl} theme={theme}>{children}</CompactLigoIde>
|
||||
}
|
||||
|
||||
return <CompactLigoIde theme={theme}>{children}</CompactLigoIde>
|
||||
}
|
||||
// Compact Ligo IDE support -- end
|
||||
|
||||
let language =
|
||||
languageClassName && languageClassName.replace(/language-/, '');
|
||||
|
||||
@ -155,7 +176,7 @@ export default ({children, className: languageClassName, metastring}) => {
|
||||
theme={prismTheme}
|
||||
code={children.trim()}
|
||||
language={language}>
|
||||
{({className, style, tokens, getLineProps, getTokenProps}) => (
|
||||
{({ className, style, tokens, getLineProps, getTokenProps }) => (
|
||||
<pre className={classnames(className, styles.codeBlock)}>
|
||||
<button
|
||||
ref={button}
|
||||
@ -172,7 +193,7 @@ export default ({children, className: languageClassName, metastring}) => {
|
||||
line[0].content = '\n'; // eslint-disable-line no-param-reassign
|
||||
}
|
||||
|
||||
const lineProps = getLineProps({line, key: i});
|
||||
const lineProps = getLineProps({ line, key: i });
|
||||
|
||||
if (highlightLines.includes(i + 1)) {
|
||||
lineProps.className = `${lineProps.className} docusaurus-highlight-code-line`;
|
||||
@ -181,7 +202,7 @@ export default ({children, className: languageClassName, metastring}) => {
|
||||
return (
|
||||
<div key={i} {...lineProps}>
|
||||
{line.map((token, key) => (
|
||||
<span key={key} {...getTokenProps({token, key})} />
|
||||
<span key={key} {...getTokenProps({ token, key })} />
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
|
@ -1057,4 +1057,12 @@ a:hover {
|
||||
.boolean-example-table > .example pre,
|
||||
.boolean-example-table > .example .codeBlockLines_src-theme-CodeBlock- {
|
||||
background-color: transparent;
|
||||
}
|
||||
}
|
||||
|
||||
.compactLigoIde {
|
||||
height: 400px;
|
||||
}
|
||||
|
||||
.compactLigoIde pre {
|
||||
border-radius: 0px;
|
||||
}
|
||||
|
@ -224,15 +224,27 @@ let print_ast_typed =
|
||||
let doc = "Subcommand: Print the typed AST.\n Warning: Intended for development of LIGO and can break at any time." in
|
||||
(Term.ret term, Term.info ~doc cmdname)
|
||||
|
||||
let optimize =
|
||||
let open Arg in
|
||||
let docv = "ENTRY_POINT" in
|
||||
let doc = "Apply Mini-C optimizations as if compiling $(docv)" in
|
||||
let info =
|
||||
info ~docv ~doc ["optimize"] in
|
||||
value @@ opt (some string) None info
|
||||
|
||||
let print_mini_c =
|
||||
let f source_file syntax display_format = (
|
||||
let f source_file syntax display_format optimize = (
|
||||
toplevel ~display_format @@
|
||||
let%bind typed,_ = Compile.Utils.type_file source_file syntax Env in
|
||||
let%bind mini_c = Compile.Of_typed.compile typed in
|
||||
ok @@ Format.asprintf "%a\n" Compile.Of_mini_c.pretty_print mini_c
|
||||
match optimize with
|
||||
| None -> ok @@ Format.asprintf "%a\n" Compile.Of_mini_c.pretty_print mini_c
|
||||
| Some entry_point ->
|
||||
let%bind mini_c = Compile.Of_mini_c.aggregate_contract mini_c entry_point in
|
||||
ok @@ Format.asprintf "%a\n" Mini_c.PP.expression mini_c
|
||||
)
|
||||
in
|
||||
let term = Term.(const f $ source_file 0 $ syntax $ display_format) in
|
||||
let term = Term.(const f $ source_file 0 $ syntax $ display_format $ optimize) in
|
||||
let cmdname = "print-mini-c" in
|
||||
let doc = "Subcommand: Print Mini-C. Warning: Intended for development of LIGO and can break at any time." in
|
||||
(Term.ret term, Term.info ~doc cmdname)
|
||||
|
@ -10,6 +10,7 @@ exception Should_exit_bad
|
||||
let () = Unix.putenv "TERM" "dumb"
|
||||
|
||||
let run_ligo args =
|
||||
Var.reset_counter ();
|
||||
let argv = Array.of_list ("ligo" :: args) in
|
||||
let result = Cli.run ~argv () in
|
||||
Term.exit_status_of_result result
|
||||
|
@ -7,16 +7,16 @@ let bad_contract basename =
|
||||
|
||||
let%expect_test _ =
|
||||
run_ligo_good [ "measure-contract" ; contract "coase.ligo" ; "main" ] ;
|
||||
[%expect {| 1872 bytes |}] ;
|
||||
[%expect {| 1874 bytes |}] ;
|
||||
|
||||
run_ligo_good [ "measure-contract" ; contract "multisig.ligo" ; "main" ] ;
|
||||
[%expect {| 1187 bytes |}] ;
|
||||
[%expect {| 1163 bytes |}] ;
|
||||
|
||||
run_ligo_good [ "measure-contract" ; contract "multisig-v2.ligo" ; "main" ] ;
|
||||
[%expect {| 2886 bytes |}] ;
|
||||
[%expect {| 2867 bytes |}] ;
|
||||
|
||||
run_ligo_good [ "measure-contract" ; contract "vote.mligo" ; "main" ] ;
|
||||
[%expect {| 581 bytes |}] ;
|
||||
[%expect {| 617 bytes |}] ;
|
||||
|
||||
run_ligo_good [ "compile-parameter" ; contract "coase.ligo" ; "main" ; "Buy_single (record card_to_buy = 1n end)" ] ;
|
||||
[%expect {| (Left (Left 1)) |}] ;
|
||||
@ -122,16 +122,18 @@ let%expect_test _ =
|
||||
PAIR ;
|
||||
PAIR ;
|
||||
DUP ;
|
||||
DIP { DUP } ;
|
||||
SWAP ;
|
||||
CDR ;
|
||||
DIP { DIP 7 { DUP } ;
|
||||
DIG 7 ;
|
||||
DIP { DIP 6 { DUP } ;
|
||||
DIG 6 ;
|
||||
SENDER ;
|
||||
PAIR ;
|
||||
SOME ;
|
||||
DIP { DIP { DUP } ; SWAP ; CAR ; CDR } } ;
|
||||
DIP { DUP ; CAR ; CDR } } ;
|
||||
UPDATE ;
|
||||
DIP { DUP } ;
|
||||
SWAP ;
|
||||
DIP { DUP } ;
|
||||
SWAP ;
|
||||
DIP { DUP ; CDR ; SWAP ; CAR ; CAR } ;
|
||||
SWAP ;
|
||||
PAIR ;
|
||||
@ -148,7 +150,7 @@ let%expect_test _ =
|
||||
DUP ;
|
||||
NIL operation ;
|
||||
PAIR ;
|
||||
DIP { DROP 11 } }
|
||||
DIP { DROP 12 } }
|
||||
{ DUP ;
|
||||
DIP { DIP 2 { DUP } ; DIG 2 } ;
|
||||
PAIR ;
|
||||
@ -317,10 +319,16 @@ let%expect_test _ =
|
||||
COMPARE ;
|
||||
NEQ ;
|
||||
IF { PUSH string "Counters does not match" ; FAILWITH }
|
||||
{ DIP 2 { DUP } ;
|
||||
DIG 2 ;
|
||||
{ DUP ;
|
||||
DIP { DIP 2 { DUP } ; DIG 2 ; CAR ; CAR } ;
|
||||
PAIR ;
|
||||
DIP { DIP { DUP } ; SWAP ; CDR ; CAR ; CHAIN_ID ; SWAP ; PAIR } ;
|
||||
PAIR ;
|
||||
PACK ;
|
||||
DIP 3 { DUP } ;
|
||||
DIG 3 ;
|
||||
CDR ;
|
||||
DIP { DIP { DUP } ; SWAP ; CAR ; CAR ; PUSH nat 0 ; SWAP ; PAIR } ;
|
||||
DIP { DIP 2 { DUP } ; DIG 2 ; CAR ; CAR ; PUSH nat 0 ; SWAP ; PAIR } ;
|
||||
ITER { SWAP ;
|
||||
PAIR ;
|
||||
DUP ;
|
||||
@ -347,16 +355,7 @@ let%expect_test _ =
|
||||
COMPARE ;
|
||||
EQ ;
|
||||
IF { DUP ;
|
||||
DIP { DIP 3 { DUP } ;
|
||||
DIG 3 ;
|
||||
CDR ;
|
||||
DIP { DIP 7 { DUP } ;
|
||||
DIG 7 ;
|
||||
DIP { DIP 9 { DUP } ; DIG 9 ; CAR ; CAR } ;
|
||||
PAIR ;
|
||||
DIP { DIP 8 { DUP } ; DIG 8 ; CDR ; CAR ; CHAIN_ID ; SWAP ; PAIR } ;
|
||||
PAIR ;
|
||||
PACK } } ;
|
||||
DIP { DIP 3 { DUP } ; DIG 3 ; CDR ; DIP { DIP 7 { DUP } ; DIG 7 } } ;
|
||||
CHECK_SIGNATURE ;
|
||||
IF { DIP 5 { DUP } ;
|
||||
DIG 5 ;
|
||||
@ -389,46 +388,31 @@ let%expect_test _ =
|
||||
{ DUP } ;
|
||||
DIP 5 { DUP } ;
|
||||
DIG 5 ;
|
||||
DIP 6 { DUP } ;
|
||||
DIG 6 ;
|
||||
CAR ;
|
||||
DIP 2 { DUP } ;
|
||||
DIG 2 ;
|
||||
CAR ;
|
||||
SWAP ;
|
||||
CDR ;
|
||||
SWAP ;
|
||||
PAIR ;
|
||||
SWAP ;
|
||||
CDR ;
|
||||
SWAP ;
|
||||
PAIR ;
|
||||
DUP ;
|
||||
DIP { DUP } ;
|
||||
SWAP ;
|
||||
CAR ;
|
||||
DIP 3 { DUP } ;
|
||||
DIG 3 ;
|
||||
CDR ;
|
||||
SWAP ;
|
||||
CAR ;
|
||||
DIP { DUP ; CDR ; SWAP ; CAR ; CDR } ;
|
||||
PAIR ;
|
||||
PAIR ;
|
||||
DIP { DUP } ;
|
||||
SWAP ;
|
||||
CDR ;
|
||||
DIP { DUP ; CDR ; SWAP ; CAR ; CAR } ;
|
||||
SWAP ;
|
||||
PAIR ;
|
||||
PAIR ;
|
||||
CAR ;
|
||||
DIP { DROP 7 } } ;
|
||||
DIP { DROP 6 } } ;
|
||||
DUP ;
|
||||
CDR ;
|
||||
DIP { DIP 2 { DUP } ; DIG 2 ; CDR ; CDR } ;
|
||||
DIP { DIP 3 { DUP } ; DIG 3 ; CDR ; CDR } ;
|
||||
COMPARE ;
|
||||
LT ;
|
||||
IF { PUSH string "Not enough signatures passed the check" ; FAILWITH }
|
||||
{ DIP 2 { DUP } ;
|
||||
DIG 2 ;
|
||||
DIP 3 { DUP } ;
|
||||
{ DIP 3 { DUP } ;
|
||||
DIG 3 ;
|
||||
DIP 4 { DUP } ;
|
||||
DIG 4 ;
|
||||
CAR ;
|
||||
CDR ;
|
||||
PUSH nat 1 ;
|
||||
@ -437,16 +421,16 @@ let%expect_test _ =
|
||||
SWAP ;
|
||||
PAIR ;
|
||||
PAIR ;
|
||||
DIP 3 { DUP } ;
|
||||
DIG 3 ;
|
||||
DIP 4 { DUP } ;
|
||||
DIG 4 ;
|
||||
DIP { DUP } ;
|
||||
SWAP ;
|
||||
DIP { DROP 2 } } ;
|
||||
DIP 3 { DUP } ;
|
||||
DIG 3 ;
|
||||
DIP 4 { DUP } ;
|
||||
DIG 4 ;
|
||||
DIP { DUP } ;
|
||||
SWAP ;
|
||||
DIP { DROP 3 } } ;
|
||||
DIP { DROP 4 } } ;
|
||||
DIP { DUP } ;
|
||||
SWAP ;
|
||||
UNIT ;
|
||||
@ -576,21 +560,23 @@ let%expect_test _ =
|
||||
DIP { DUP } ;
|
||||
SWAP ;
|
||||
DIP { DROP 2 } } ;
|
||||
DIP 2 { DUP } ;
|
||||
DIG 2 ;
|
||||
CAR ;
|
||||
DIP { DUP } ;
|
||||
PAIR ;
|
||||
DIP 2 { DUP } ;
|
||||
DIG 2 ;
|
||||
SWAP ;
|
||||
PUSH bool True ;
|
||||
SENDER ;
|
||||
UPDATE ;
|
||||
DIP 3 { DUP } ;
|
||||
DIG 3 ;
|
||||
DIP 2 { DUP } ;
|
||||
DIG 2 ;
|
||||
SWAP ;
|
||||
CAR ;
|
||||
PAIR ;
|
||||
CDR ;
|
||||
DIP { DUP } ;
|
||||
SWAP ;
|
||||
PAIR ;
|
||||
DIP { DROP 2 } } ;
|
||||
DIP { DROP 3 } } ;
|
||||
DUP ;
|
||||
CAR ;
|
||||
DIP { DUP } ;
|
||||
@ -697,12 +683,9 @@ let%expect_test _ =
|
||||
{ DIP { DUP } ; SWAP } ;
|
||||
DIP 3 { DUP } ;
|
||||
DIG 3 ;
|
||||
DIP 4 { DUP } ;
|
||||
DIG 4 ;
|
||||
CAR ;
|
||||
DIP 2 { DUP } ;
|
||||
DIG 2 ;
|
||||
DIP { DROP ; CDR } ;
|
||||
CDR ;
|
||||
DIP { DUP } ;
|
||||
SWAP ;
|
||||
PAIR ;
|
||||
CAR ;
|
||||
DIP { DROP 4 } } ;
|
||||
@ -887,14 +870,16 @@ let%expect_test _ =
|
||||
PAIR ;
|
||||
DUP ;
|
||||
CDR ;
|
||||
DIP { DUP } ;
|
||||
SWAP ;
|
||||
NOW ;
|
||||
SENDER ;
|
||||
DIP 3 { DUP } ;
|
||||
DIG 3 ;
|
||||
CAR ;
|
||||
IF_LEFT
|
||||
{ DIP { DUP } ;
|
||||
SWAP ;
|
||||
DIP 2 { DUP } ;
|
||||
DIG 2 ;
|
||||
{ DIP 3 { DUP } ;
|
||||
DIG 3 ;
|
||||
DIP 4 { DUP } ;
|
||||
DIG 4 ;
|
||||
CAR ;
|
||||
CAR ;
|
||||
CDR ;
|
||||
@ -906,10 +891,10 @@ let%expect_test _ =
|
||||
PAIR ;
|
||||
PAIR ;
|
||||
DIP { DROP } }
|
||||
{ DIP { DUP } ;
|
||||
SWAP ;
|
||||
DIP 2 { DUP } ;
|
||||
DIG 2 ;
|
||||
{ DIP 3 { DUP } ;
|
||||
DIG 3 ;
|
||||
DIP 4 { DUP } ;
|
||||
DIG 4 ;
|
||||
CDR ;
|
||||
CDR ;
|
||||
PUSH nat 1 ;
|
||||
@ -921,12 +906,9 @@ let%expect_test _ =
|
||||
PAIR ;
|
||||
DIP { DROP } } ;
|
||||
DUP ;
|
||||
DIP { DUP } ;
|
||||
SWAP ;
|
||||
CDR ;
|
||||
CAR ;
|
||||
PUSH bool True ;
|
||||
SENDER ;
|
||||
DIP 2 { DUP } ;
|
||||
DIG 2 ;
|
||||
DIP { DIP { DUP } ; SWAP ; CDR ; CAR ; PUSH bool True } ;
|
||||
UPDATE ;
|
||||
DIP { DUP ; CAR ; SWAP ; CDR ; CDR } ;
|
||||
PAIR ;
|
||||
@ -934,7 +916,7 @@ let%expect_test _ =
|
||||
PAIR ;
|
||||
NIL operation ;
|
||||
PAIR ;
|
||||
DIP { DROP 4 } } ;
|
||||
DIP { DROP 6 } } ;
|
||||
DIP { DROP } } } |}]
|
||||
|
||||
let%expect_test _ =
|
||||
@ -950,6 +932,32 @@ let%expect_test _ =
|
||||
PAIR ;
|
||||
DIP { DROP 2 } } } |}]
|
||||
|
||||
let%expect_test _ =
|
||||
run_ligo_good [ "compile-contract" ; contract "amount_lambda.mligo" ; "main" ] ;
|
||||
(* AMOUNT should occur inside the second lambda, but not the first lambda *)
|
||||
[%expect {|
|
||||
{ parameter bool ;
|
||||
storage (lambda unit mutez) ;
|
||||
code { DUP ;
|
||||
CAR ;
|
||||
IF { AMOUNT ;
|
||||
DUP ;
|
||||
LAMBDA
|
||||
(pair mutez unit)
|
||||
mutez
|
||||
{ DUP ; CAR ; SWAP ; CDR ; DIP { DUP } ; SWAP ; DIP { DROP 2 } } ;
|
||||
SWAP ;
|
||||
APPLY ;
|
||||
DIP { DROP } }
|
||||
{ LAMBDA unit mutez { DROP ; AMOUNT } } ;
|
||||
NIL operation ;
|
||||
PAIR ;
|
||||
DIP { DROP } } } |}]
|
||||
|
||||
let%expect_test _ =
|
||||
run_ligo_good [ "print-ast-typed" ; contract "sequence.mligo" ; ];
|
||||
[%expect {| const y = lambda (_) return let x = +1 in let _ = let x = +2 in UNIT() in let _ = let x = +23 in UNIT() in let _ = let x = +42 in UNIT() in x |}]
|
||||
|
||||
let%expect_test _ =
|
||||
run_ligo_bad [ "compile-contract" ; contract "bad_type_operator.ligo" ; "main" ] ;
|
||||
[%expect {|
|
||||
@ -963,16 +971,6 @@ let%expect_test _ =
|
||||
* Open a gitlab issue: https://gitlab.com/ligolang/ligo/issues/new
|
||||
* Check the changelog by running 'ligo changelog' |}]
|
||||
|
||||
let%expect_test _ =
|
||||
run_ligo_good [ "run-function" ; contract "failwith.ligo" ; "failer" ; "1" ] ;
|
||||
[%expect {|
|
||||
failwith("some_string") |}]
|
||||
|
||||
let%expect_test _ =
|
||||
run_ligo_good [ "run-function" ; contract "failwith.ligo" ; "failer" ; "1" ; "--format=json" ] ;
|
||||
[%expect {|
|
||||
{"status":"ok","content":"failwith(\"some_string\")"} |}]
|
||||
|
||||
let%expect_test _ =
|
||||
run_ligo_bad [ "compile-contract" ; contract "bad_address_format.religo" ; "main" ] ;
|
||||
[%expect {|
|
||||
@ -1084,7 +1082,7 @@ let%expect_test _ =
|
||||
let%expect_test _ =
|
||||
run_ligo_bad [ "compile-contract" ; bad_contract "create_contract_toplevel.mligo" ; "main" ] ;
|
||||
[%expect {|
|
||||
ligo: in file "create_contract_toplevel.mligo", line 4, character 35 to line 8, character 8. No free variable allowed in this lambda: variable 'store' {"expression":"CREATE_CONTRACT(lambda (#P:Some(( nat * string ))) : None return\n let rhs#727 = #P in\n let p = rhs#727.0 in\n let s = rhs#727.1 in\n ( LIST_EMPTY() : (type_operator: list(operation)) , store ) ,\n NONE() : (type_operator: option(key_hash)) ,\n 300000000mutez ,\n \"un\")","location":"in file \"create_contract_toplevel.mligo\", line 4, character 35 to line 8, character 8"}
|
||||
ligo: in file "create_contract_toplevel.mligo", line 4, character 35 to line 8, character 8. No free variable allowed in this lambda: variable 'store' {"expression":"CREATE_CONTRACT(lambda (#P:Some(( nat * string ))) : None return\n let rhs#2 = #P in\n let p = rhs#2.0 in\n let s = rhs#2.1 in\n ( LIST_EMPTY() : (type_operator: list(operation)) , store ) ,\n NONE() : (type_operator: option(key_hash)) ,\n 300000000mutez ,\n \"un\")","location":"in file \"create_contract_toplevel.mligo\", line 4, character 35 to line 8, character 8"}
|
||||
|
||||
|
||||
If you're not sure how to fix this error, you can
|
||||
@ -1097,7 +1095,7 @@ ligo: in file "create_contract_toplevel.mligo", line 4, character 35 to line 8,
|
||||
|
||||
run_ligo_bad [ "compile-contract" ; bad_contract "create_contract_var.mligo" ; "main" ] ;
|
||||
[%expect {|
|
||||
ligo: in file "create_contract_var.mligo", line 6, character 35 to line 10, character 5. No free variable allowed in this lambda: variable 'a' {"expression":"CREATE_CONTRACT(lambda (#P:Some(( nat * int ))) : None return\n let rhs#730 = #P in\n let p = rhs#730.0 in\n let s = rhs#730.1 in\n ( LIST_EMPTY() : (type_operator: list(operation)) , a ) ,\n NONE() : (type_operator: option(key_hash)) ,\n 300000000mutez ,\n 1)","location":"in file \"create_contract_var.mligo\", line 6, character 35 to line 10, character 5"}
|
||||
ligo: in file "create_contract_var.mligo", line 6, character 35 to line 10, character 5. No free variable allowed in this lambda: variable 'a' {"expression":"CREATE_CONTRACT(lambda (#P:Some(( nat * int ))) : None return\n let rhs#2 = #P in\n let p = rhs#2.0 in\n let s = rhs#2.1 in\n ( LIST_EMPTY() : (type_operator: list(operation)) , a ) ,\n NONE() : (type_operator: option(key_hash)) ,\n 300000000mutez ,\n 1)","location":"in file \"create_contract_var.mligo\", line 6, character 35 to line 10, character 5"}
|
||||
|
||||
|
||||
If you're not sure how to fix this error, you can
|
||||
|
@ -8,11 +8,11 @@ let bad_contract basename =
|
||||
let%expect_test _ =
|
||||
run_ligo_good [ "run-function" ; contract "failwith.ligo" ; "failer" ; "1" ] ;
|
||||
[%expect {|
|
||||
failwith("some_string") |}];
|
||||
failwith(42) |}];
|
||||
|
||||
run_ligo_good [ "run-function" ; contract "failwith.ligo" ; "failer" ; "1" ; "--format=json" ] ;
|
||||
[%expect {|
|
||||
{"status":"ok","content":"failwith(\"some_string\")"} |}];
|
||||
{"status":"ok","content":"failwith(42)"} |}];
|
||||
|
||||
|
||||
run_ligo_good [ "dry-run" ; contract "subtle_nontail_fail.mligo" ; "main" ; "()" ; "()" ] ;
|
||||
|
@ -189,4 +189,17 @@ let%expect_test _ =
|
||||
* Visit our documentation: https://ligolang.org/docs/intro/introduction
|
||||
* Ask a question on our Discord: https://discord.gg/9rhYaEt
|
||||
* Open a gitlab issue: https://gitlab.com/ligolang/ligo/issues/new
|
||||
* Check the changelog by running 'ligo changelog' |}];
|
||||
* Check the changelog by running 'ligo changelog' |}]
|
||||
|
||||
let%expect_test _ =
|
||||
run_ligo_bad [ "compile-contract" ; "../../test/contracts/negative/failwith_wrong_type.ligo" ; "main" ] ;
|
||||
[%expect {|
|
||||
ligo: in file "failwith_wrong_type.ligo", line 2, characters 19-46. Failwith with disallowed type: Expected arguments with one of the following combinations of types: failwith(string) or failwith(nat) or failwith(int) but got this combination instead: failwith((type_operator: list(int)))
|
||||
|
||||
If you're not sure how to fix this error, you can
|
||||
do one of the following:
|
||||
|
||||
* Visit our documentation: https://ligolang.org/docs/intro/introduction
|
||||
* Ask a question on our Discord: https://discord.gg/9rhYaEt
|
||||
* Open a gitlab issue: https://gitlab.com/ligolang/ligo/issues/new
|
||||
* Check the changelog by running 'ligo changelog' |}]
|
||||
|
@ -33,4 +33,16 @@ let aggregate_and_compile_expression = fun program exp ->
|
||||
aggregate_and_compile program (ExpressionForm exp)
|
||||
|
||||
let pretty_print program =
|
||||
Mini_c.PP.program program
|
||||
Mini_c.PP.program program
|
||||
|
||||
|
||||
(* TODO refactor? *)
|
||||
|
||||
let aggregate = fun program form ->
|
||||
let%bind aggregated = aggregate_entry program form in
|
||||
ok @@ Self_mini_c.all_expression aggregated
|
||||
|
||||
let aggregate_contract = fun (program : Types.program) name ->
|
||||
let%bind (exp, idx) = get_entry program name in
|
||||
let program' = List.take idx program in
|
||||
aggregate program' (ContractForm exp)
|
||||
|
@ -933,6 +933,17 @@ sequence_or_record_in:
|
||||
| None ->
|
||||
PaRecord {r_elts = ($1, []); r_terminator = None}
|
||||
}
|
||||
| field_name more_field_assignments {
|
||||
let value = {
|
||||
field_name = $1;
|
||||
assignment = ghost;
|
||||
field_expr = EVar $1 }
|
||||
in
|
||||
let field_name = {$1 with value} in
|
||||
let (comma, elts) = $2 in
|
||||
let r_elts = Utils.nsepseq_cons field_name comma elts in
|
||||
PaRecord {r_elts; r_terminator = None}
|
||||
}
|
||||
|
||||
sequence_or_record:
|
||||
"{" sequence_or_record_in "}" {
|
||||
|
@ -474,14 +474,29 @@ and transpile_annotated_expression (ae:AST.expression) : expression result =
|
||||
let expr = List.fold_left aux record' path in
|
||||
ok expr
|
||||
| E_record_update {record; path; update} ->
|
||||
let%bind ty' = transpile_type (get_type_expression record) in
|
||||
let%bind ty_lmap =
|
||||
trace_strong (corner_case ~loc:__LOC__ "not a record") @@
|
||||
get_t_record (get_type_expression record) in
|
||||
let%bind ty'_lmap = Ast_typed.Helpers.bind_map_lmap_t transpile_type ty_lmap in
|
||||
let%bind path =
|
||||
trace_strong (corner_case ~loc:__LOC__ "record access") @@
|
||||
record_access_to_lr ty' ty'_lmap path in
|
||||
let rec aux res (r,p,up) =
|
||||
let ty = get_type_expression r in
|
||||
let%bind ty_lmap =
|
||||
trace_strong (corner_case ~loc:__LOC__ "not a record") @@
|
||||
get_t_record (ty) in
|
||||
let%bind ty' = transpile_type (ty) in
|
||||
let%bind ty'_lmap = Ast_typed.Helpers.bind_map_lmap_t transpile_type ty_lmap in
|
||||
let%bind p' =
|
||||
trace_strong (corner_case ~loc:__LOC__ "record access") @@
|
||||
record_access_to_lr ty' ty'_lmap p in
|
||||
let res' = res @ p' in
|
||||
match (up:AST.expression).expression_content with
|
||||
| AST.E_record_update {record=record'; path=path'; update=update'} -> (
|
||||
match record'.expression_content with
|
||||
| AST.E_record_accessor {record;path} ->
|
||||
if (AST.Misc.equal_variables record r && path = p) then
|
||||
aux res' (record',path',update')
|
||||
else ok @@ (up,res')
|
||||
| _ -> ok @@ (up,res')
|
||||
)
|
||||
| _ -> ok @@ (up,res')
|
||||
in
|
||||
let%bind (update, path) = aux [] (record, path, update) in
|
||||
let path = List.map snd path in
|
||||
let%bind update = transpile_annotated_expression update in
|
||||
let%bind record = transpile_annotated_expression record in
|
||||
|
@ -25,12 +25,13 @@ let is_pure_constant : constant' -> bool =
|
||||
| C_SOME
|
||||
| C_UPDATE | C_MAP_FIND_OPT | C_MAP_ADD | C_MAP_UPDATE
|
||||
| C_INT | C_ABS | C_IS_NAT
|
||||
| C_BALANCE | C_AMOUNT | C_ADDRESS | C_NOW | C_SOURCE | C_SENDER | C_CHAIN_ID
|
||||
| C_ADDRESS
|
||||
| C_SET_MEM | C_SET_ADD | C_SET_REMOVE | C_SLICE
|
||||
| C_SHA256 | C_SHA512 | C_BLAKE2b | C_CHECK_SIGNATURE
|
||||
| C_HASH_KEY | C_BYTES_PACK | C_CONCAT
|
||||
-> true
|
||||
(* unfortunately impure: *)
|
||||
| C_BALANCE | C_AMOUNT | C_NOW | C_SOURCE | C_SENDER | C_CHAIN_ID
|
||||
| C_ADD | C_SUB |C_MUL|C_DIV|C_MOD | C_LSL | C_LSR
|
||||
(* impure: *)
|
||||
| C_ASSERTION | C_ASSERT_INFERRED
|
||||
|
@ -634,22 +634,22 @@ let rec compile_expression :
|
||||
| ESeq s -> (
|
||||
let (s , loc) = r_split s in
|
||||
let items : Raw.expr list = pseq_to_list s.elements in
|
||||
(match items with
|
||||
(match List.rev items with
|
||||
[] -> return @@ e_skip ~loc ()
|
||||
| expr::more ->
|
||||
let expr' = compile_expression expr in
|
||||
let apply (e1: Raw.expr) (e2: expression Trace.result) =
|
||||
let%bind a = compile_expression e1 in
|
||||
let%bind e2' = e2 in
|
||||
return @@ e_sequence a e2'
|
||||
in List.fold_right apply more expr')
|
||||
let apply e1 e2 =
|
||||
let%bind a = compile_expression e2 in
|
||||
let%bind e1' = e1 in
|
||||
return @@ e_sequence a e1'
|
||||
in List.fold_left apply expr' more)
|
||||
)
|
||||
| ECond c -> (
|
||||
let (c , loc) = r_split c in
|
||||
let%bind expr = compile_expression c.test in
|
||||
let%bind match_true = compile_expression c.ifso in
|
||||
let%bind match_false = compile_expression c.ifnot in
|
||||
return @@ e_matching ~loc expr (Match_bool {match_true; match_false})
|
||||
return @@ e_cond ~loc expr match_true match_false
|
||||
)
|
||||
|
||||
and compile_fun lamb' : expr result =
|
||||
|
@ -398,7 +398,7 @@ let rec compile_expression (t:Raw.expr) : expr result =
|
||||
let%bind expr = compile_expression c.test in
|
||||
let%bind match_true = compile_expression c.ifso in
|
||||
let%bind match_false = compile_expression c.ifnot in
|
||||
return @@ e_matching expr ~loc (Match_bool {match_true; match_false})
|
||||
return @@ e_cond ~loc expr match_true match_false
|
||||
|
||||
| ECase c -> (
|
||||
let (c , loc) = r_split c in
|
||||
@ -860,7 +860,7 @@ and compile_single_instruction : Raw.instruction -> (_ -> expression result) res
|
||||
|
||||
let%bind match_true = match_true None in
|
||||
let%bind match_false = match_false None in
|
||||
return_statement @@ e_matching expr ~loc (Match_bool {match_true; match_false})
|
||||
return_statement @@ e_cond ~loc expr match_true match_false
|
||||
)
|
||||
| Assign a -> (
|
||||
let (a , loc) = r_split a in
|
||||
|
@ -52,8 +52,16 @@ let repair_mutable_variable_in_matching (match_body : O.expression) (element_nam
|
||||
| E_constant {cons_name=C_MAP_FOLD;arguments= _}
|
||||
| E_constant {cons_name=C_SET_FOLD;arguments= _}
|
||||
| E_constant {cons_name=C_LIST_FOLD;arguments= _}
|
||||
| E_cond _
|
||||
| E_matching _ -> ok @@ (false, (decl_var,free_var),ass_exp)
|
||||
| _ -> ok (true, (decl_var, free_var),ass_exp)
|
||||
| E_constant _
|
||||
| E_skip
|
||||
| E_literal _ | E_variable _
|
||||
| E_application _ | E_lambda _| E_recursive _
|
||||
| E_constructor _ | E_record _| E_record_accessor _|E_record_update _
|
||||
| E_ascription _ | E_sequence _ | E_tuple _ | E_tuple_accessor _ | E_tuple_update _
|
||||
| E_map _ | E_big_map _ |E_list _ | E_set _ |E_look_up _
|
||||
-> ok (true, (decl_var, free_var),ass_exp)
|
||||
)
|
||||
(element_names,[])
|
||||
match_body in
|
||||
@ -88,8 +96,16 @@ and repair_mutable_variable_in_loops (for_body : O.expression) (element_names :
|
||||
| E_constant {cons_name=C_MAP_FOLD;arguments= _}
|
||||
| E_constant {cons_name=C_SET_FOLD;arguments= _}
|
||||
| E_constant {cons_name=C_LIST_FOLD;arguments= _}
|
||||
| E_cond _
|
||||
| E_matching _ -> ok @@ (false,(decl_var,free_var),ass_exp)
|
||||
| _ -> ok (true,(decl_var, free_var),ass_exp)
|
||||
| E_constant _
|
||||
| E_skip
|
||||
| E_literal _ | E_variable _
|
||||
| E_application _ | E_lambda _| E_recursive _
|
||||
| E_constructor _ | E_record _| E_record_accessor _|E_record_update _
|
||||
| E_ascription _ | E_sequence _ | E_tuple _ | E_tuple_accessor _ | E_tuple_update _
|
||||
| E_map _ | E_big_map _ |E_list _ | E_set _ |E_look_up _
|
||||
-> ok (true, (decl_var, free_var),ass_exp)
|
||||
)
|
||||
(element_names,[])
|
||||
for_body in
|
||||
@ -102,12 +118,14 @@ and store_mutable_variable (free_vars : I.expression_variable list) =
|
||||
let aux var = (O.Label (Var.to_name var), O.e_variable var) in
|
||||
O.e_record @@ O.LMap.of_list (List.map aux free_vars)
|
||||
|
||||
and restore_mutable_variable (expr : O.expression->O.expression_content) (free_vars : O.expression_variable list) (env : O.expression_variable) =
|
||||
and restore_mutable_variable (expr : O.expression->O.expression) (free_vars : O.expression_variable list) (env : O.expression_variable) =
|
||||
let aux (f: O.expression -> O.expression) (ev: O.expression_variable) =
|
||||
fun expr -> f (O.e_let_in (ev,None) true false (O.e_record_accessor (O.e_variable env) (Label (Var.to_name ev))) expr)
|
||||
in
|
||||
let ef = List.fold_left aux (fun e -> e) free_vars in
|
||||
expr (ef (O.e_skip ()))
|
||||
fun e -> match e with
|
||||
| None -> expr (ef (O.e_skip ()))
|
||||
| Some e -> expr (ef e)
|
||||
|
||||
|
||||
let rec compile_type_expression : I.type_expression -> O.type_expression result =
|
||||
@ -189,79 +207,88 @@ and compile_type_operator : I.type_operator -> O.type_operator result =
|
||||
|
||||
let rec compile_expression : I.expression -> O.expression result =
|
||||
fun e ->
|
||||
let return expr = ok @@ O.make_e ~loc:e.location expr in
|
||||
let%bind e = compile_expression' e in
|
||||
ok @@ e None
|
||||
|
||||
and compile_expression' : I.expression -> (O.expression option -> O.expression) result =
|
||||
fun e ->
|
||||
let return expr = ok @@ function
|
||||
| None -> expr
|
||||
| Some e -> O.e_sequence expr e
|
||||
in
|
||||
let loc = e.location in
|
||||
match e.expression_content with
|
||||
| I.E_literal literal -> return @@ O.E_literal literal
|
||||
| I.E_literal literal -> return @@ O.e_literal ~loc literal
|
||||
| I.E_constant {cons_name;arguments} ->
|
||||
let%bind arguments = bind_map_list compile_expression arguments in
|
||||
return @@ O.E_constant {cons_name;arguments}
|
||||
| I.E_variable name -> return @@ O.E_variable name
|
||||
return @@ O.e_constant ~loc cons_name arguments
|
||||
| I.E_variable name -> return @@ O.e_variable ~loc name
|
||||
| I.E_application {lamb;args} ->
|
||||
let%bind lamb = compile_expression lamb in
|
||||
let%bind args = compile_expression args in
|
||||
return @@ O.E_application {lamb;args}
|
||||
return @@ O.e_application ~loc lamb args
|
||||
| I.E_lambda lambda ->
|
||||
let%bind lambda = compile_lambda lambda in
|
||||
return @@ O.E_lambda lambda
|
||||
return @@ O.make_e ~loc (O.E_lambda lambda)
|
||||
| I.E_recursive {fun_name;fun_type;lambda} ->
|
||||
let%bind fun_type = compile_type_expression fun_type in
|
||||
let%bind lambda = compile_lambda lambda in
|
||||
return @@ O.E_recursive {fun_name;fun_type;lambda}
|
||||
return @@ O.e_recursive ~loc fun_name fun_type lambda
|
||||
| I.E_let_in {let_binder;inline;rhs;let_result} ->
|
||||
let (binder,ty_opt) = let_binder in
|
||||
let%bind ty_opt = bind_map_option compile_type_expression ty_opt in
|
||||
let%bind rhs = compile_expression rhs in
|
||||
let%bind let_result = compile_expression let_result in
|
||||
return @@ O.E_let_in {let_binder=(binder,ty_opt);mut=false;inline;rhs;let_result}
|
||||
return @@ O.e_let_in ~loc (binder,ty_opt) false inline rhs let_result
|
||||
| I.E_constructor {constructor;element} ->
|
||||
let%bind element = compile_expression element in
|
||||
return @@ O.E_constructor {constructor;element}
|
||||
return @@ O.e_constructor ~loc constructor element
|
||||
| I.E_matching m ->
|
||||
let%bind m = compile_matching m in
|
||||
return @@ m
|
||||
ok @@ m
|
||||
| I.E_record record ->
|
||||
let record = I.LMap.to_kv_list record in
|
||||
let%bind record =
|
||||
bind_map_list (fun (k,v) ->
|
||||
let%bind v =compile_expression v in
|
||||
let%bind v = compile_expression v in
|
||||
ok @@ (k,v)
|
||||
) record
|
||||
in
|
||||
return @@ O.E_record (O.LMap.of_list record)
|
||||
return @@ O.e_record ~loc (O.LMap.of_list record)
|
||||
| I.E_record_accessor {record;path} ->
|
||||
let%bind record = compile_expression record in
|
||||
return @@ O.E_record_accessor {record;path}
|
||||
return @@ O.e_record_accessor ~loc record path
|
||||
| I.E_record_update {record;path;update} ->
|
||||
let%bind record = compile_expression record in
|
||||
let%bind update = compile_expression update in
|
||||
return @@ O.E_record_update {record;path;update}
|
||||
return @@ O.e_record_update ~loc record path update
|
||||
| I.E_map map ->
|
||||
let%bind map = bind_map_list (
|
||||
bind_map_pair compile_expression
|
||||
) map
|
||||
in
|
||||
return @@ O.E_map map
|
||||
return @@ O.e_map ~loc map
|
||||
| I.E_big_map big_map ->
|
||||
let%bind big_map = bind_map_list (
|
||||
bind_map_pair compile_expression
|
||||
) big_map
|
||||
in
|
||||
return @@ O.E_big_map big_map
|
||||
return @@ O.e_big_map ~loc big_map
|
||||
| I.E_list lst ->
|
||||
let%bind lst = bind_map_list compile_expression lst in
|
||||
return @@ O.E_list lst
|
||||
return @@ O.e_list ~loc lst
|
||||
| I.E_set set ->
|
||||
let%bind set = bind_map_list compile_expression set in
|
||||
return @@ O.E_set set
|
||||
return @@ O.e_set ~loc set
|
||||
| I.E_look_up look_up ->
|
||||
let%bind look_up = bind_map_pair compile_expression look_up in
|
||||
return @@ O.E_look_up look_up
|
||||
let%bind (a,b) = bind_map_pair compile_expression look_up in
|
||||
return @@ O.e_look_up ~loc a b
|
||||
| I.E_ascription {anno_expr; type_annotation} ->
|
||||
let%bind anno_expr = compile_expression anno_expr in
|
||||
let%bind type_annotation = compile_type_expression type_annotation in
|
||||
return @@ O.E_ascription {anno_expr; type_annotation}
|
||||
return @@ O.e_annotation ~loc anno_expr type_annotation
|
||||
| I.E_cond {condition;then_clause;else_clause} ->
|
||||
let%bind condition = compile_expression condition in
|
||||
let%bind condition = compile_expression condition in
|
||||
let%bind then_clause' = compile_expression then_clause in
|
||||
let%bind else_clause' = compile_expression else_clause in
|
||||
let env = Var.fresh () in
|
||||
@ -274,71 +301,73 @@ let rec compile_expression : I.expression -> O.expression result =
|
||||
if (List.length free_vars != 0) then
|
||||
let cond_expr = O.e_cond condition then_clause else_clause in
|
||||
let return_expr = fun expr ->
|
||||
O.E_let_in {let_binder=(env,None); mut=false; inline=false;rhs=(store_mutable_variable free_vars);
|
||||
let_result=O.e_let_in (env,None) false false cond_expr @@
|
||||
O.e_let_in (env,None) false false (store_mutable_variable free_vars) @@
|
||||
O.e_let_in (env,None) false false cond_expr @@
|
||||
expr
|
||||
}
|
||||
in
|
||||
return @@ restore_mutable_variable return_expr free_vars env
|
||||
ok @@ restore_mutable_variable return_expr free_vars env
|
||||
else
|
||||
return @@ O.E_cond {condition; then_clause=then_clause'; else_clause=else_clause'}
|
||||
return @@ O.e_cond ~loc condition then_clause' else_clause'
|
||||
| I.E_sequence {expr1; expr2} ->
|
||||
let%bind expr1 = compile_expression expr1 in
|
||||
let%bind expr2 = compile_expression expr2 in
|
||||
ok @@ add_to_end expr1 expr2
|
||||
| I.E_skip -> return @@ O.E_skip
|
||||
let%bind expr1 = compile_expression' expr1 in
|
||||
let%bind expr2 = compile_expression' expr2 in
|
||||
ok @@ fun e -> (match e with
|
||||
| None -> expr1 (Some (expr2 None))
|
||||
| Some e -> expr1 (Some (expr2 (Some e)))
|
||||
)
|
||||
| I.E_skip -> return @@ O.e_skip ~loc ()
|
||||
| I.E_tuple tuple ->
|
||||
let%bind tuple = bind_map_list compile_expression tuple in
|
||||
return @@ O.E_tuple (tuple)
|
||||
return @@ O.e_tuple ~loc tuple
|
||||
| I.E_tuple_accessor {tuple;path} ->
|
||||
let%bind tuple = compile_expression tuple in
|
||||
return @@ O.E_tuple_accessor {tuple;path}
|
||||
return @@ O.e_tuple_accessor ~loc tuple path
|
||||
| I.E_tuple_update {tuple;path;update} ->
|
||||
let%bind tuple = compile_expression tuple in
|
||||
let%bind update = compile_expression update in
|
||||
return @@ O.E_tuple_update {tuple;path;update}
|
||||
| I.E_assign ass ->
|
||||
let%bind content = compile_assign ass @@ O.e_skip () in
|
||||
return @@ content
|
||||
return @@ O.e_tuple_update ~loc tuple path update
|
||||
| I.E_assign {variable; access_path; expression} ->
|
||||
let accessor ?loc s a =
|
||||
match a with
|
||||
I.Access_tuple _i -> failwith "adding tuple soon"
|
||||
| I.Access_record a -> ok @@ O.e_record_accessor ?loc s (Label a)
|
||||
| I.Access_map k ->
|
||||
let%bind k = compile_expression k in
|
||||
ok @@ O.e_constant ?loc C_MAP_FIND_OPT [k;s]
|
||||
in
|
||||
let update ?loc (s:O.expression) a e =
|
||||
match a with
|
||||
I.Access_tuple _i -> failwith "adding tuple soon"
|
||||
| I.Access_record a -> ok @@ O.e_record_update ?loc s (Label a) e
|
||||
| I.Access_map k ->
|
||||
let%bind k = compile_expression k in
|
||||
ok @@ O.e_constant ?loc C_UPDATE [k;O.e_some (e);s]
|
||||
in
|
||||
let aux (s, e : O.expression * _) lst =
|
||||
let%bind s' = accessor ~loc:s.location s lst in
|
||||
let e' = fun expr ->
|
||||
let%bind u = update ~loc:s.location s lst (expr)
|
||||
in e u
|
||||
in
|
||||
ok @@ (s',e')
|
||||
in
|
||||
let%bind (_,rhs) = bind_fold_list aux (O.e_variable variable, fun e -> ok @@ e) access_path in
|
||||
let%bind expression = compile_expression expression in
|
||||
let%bind rhs = rhs @@ expression in
|
||||
ok @@ fun expr -> (match expr with
|
||||
| None -> O.e_let_in ~loc (variable,None) true false rhs (O.e_skip ())
|
||||
| Some e -> O.e_let_in ~loc (variable, None) true false rhs e
|
||||
)
|
||||
| I.E_for f ->
|
||||
let%bind f = compile_for f in
|
||||
return @@ f
|
||||
ok @@ f
|
||||
| I.E_for_each fe ->
|
||||
let%bind fe = compile_for_each fe in
|
||||
return @@ fe
|
||||
ok @@ fe
|
||||
| I.E_while w ->
|
||||
let%bind w = compile_while w in
|
||||
return @@ w
|
||||
ok @@ w
|
||||
|
||||
and compile_assign {variable; access_path; expression} expr =
|
||||
let accessor ?loc s a =
|
||||
match a with
|
||||
I.Access_tuple _i -> failwith "adding tuple soon"
|
||||
| I.Access_record a -> ok @@ O.e_record_accessor ?loc s (Label a)
|
||||
| I.Access_map k ->
|
||||
let%bind k = compile_expression k in
|
||||
ok @@ O.e_constant ?loc C_MAP_FIND_OPT [k;s]
|
||||
in
|
||||
let update ?loc (s:O.expression) a e =
|
||||
match a with
|
||||
I.Access_tuple _i -> failwith "adding tuple soon"
|
||||
| I.Access_record a -> ok @@ O.e_record_update ?loc s (Label a) e
|
||||
| I.Access_map k ->
|
||||
let%bind k = compile_expression k in
|
||||
ok @@ O.e_constant ?loc C_UPDATE [k;O.e_some (e);s]
|
||||
in
|
||||
let aux (s, e : O.expression * _) lst =
|
||||
let%bind s' = accessor ~loc:s.location s lst in
|
||||
let e' = fun expr ->
|
||||
let%bind u = update ~loc:s.location s lst (expr)
|
||||
in e u
|
||||
in
|
||||
ok @@ (s',e')
|
||||
in
|
||||
let%bind (_,rhs) = bind_fold_list aux (O.e_variable variable, fun e -> ok @@ e) access_path in
|
||||
let%bind expression = compile_expression expression in
|
||||
let%bind rhs = rhs @@ expression in
|
||||
ok @@ O.E_let_in {let_binder=(variable,None); mut=true; rhs; let_result=expr;inline = false}
|
||||
|
||||
and compile_lambda : I.lambda -> O.lambda result =
|
||||
fun {binder;input_type;output_type;result}->
|
||||
@ -347,8 +376,12 @@ and compile_lambda : I.lambda -> O.lambda result =
|
||||
let%bind result = compile_expression result in
|
||||
ok @@ O.{binder;input_type;output_type;result}
|
||||
|
||||
and compile_matching : I.matching -> O.expression_content result =
|
||||
and compile_matching : I.matching -> (O.expression option -> O.expression) result =
|
||||
fun {matchee;cases} ->
|
||||
let return expr = ok @@ function
|
||||
| None -> expr
|
||||
| Some e -> O.e_sequence expr e
|
||||
in
|
||||
let%bind matchee = compile_expression matchee in
|
||||
match cases with
|
||||
| I.Match_bool {match_true;match_false} ->
|
||||
@ -364,14 +397,13 @@ and compile_matching : I.matching -> O.expression_content result =
|
||||
if (List.length free_vars != 0) then
|
||||
let match_expr = O.e_matching matchee (O.Match_bool {match_true; match_false}) in
|
||||
let return_expr = fun expr ->
|
||||
O.E_let_in {let_binder=(env,None); mut=false; inline=false;rhs=(store_mutable_variable free_vars);
|
||||
let_result=O.e_let_in (env,None) false false match_expr @@
|
||||
O.e_let_in (env,None) false false (store_mutable_variable free_vars) @@
|
||||
O.e_let_in (env,None) false false match_expr @@
|
||||
expr
|
||||
}
|
||||
in
|
||||
ok @@ restore_mutable_variable return_expr free_vars env
|
||||
else
|
||||
ok @@ O.E_matching {matchee;cases=O.Match_bool {match_true=match_true';match_false=match_false'}}
|
||||
return @@ O.e_matching matchee @@ O.Match_bool {match_true=match_true';match_false=match_false'}
|
||||
| I.Match_option {match_none;match_some} ->
|
||||
let%bind match_none' = compile_expression match_none in
|
||||
let (n,expr,tv) = match_some in
|
||||
@ -385,14 +417,13 @@ and compile_matching : I.matching -> O.expression_content result =
|
||||
if (List.length free_vars != 0) then
|
||||
let match_expr = O.e_matching matchee (O.Match_option {match_none; match_some=(n,expr,tv)}) in
|
||||
let return_expr = fun expr ->
|
||||
O.E_let_in {let_binder=(env,None); mut=false; inline=false;rhs=(store_mutable_variable free_vars);
|
||||
let_result=O.e_let_in (env,None) false false match_expr @@
|
||||
O.e_let_in (env,None) false false (store_mutable_variable free_vars) @@
|
||||
O.e_let_in (env,None) false false match_expr @@
|
||||
expr
|
||||
}
|
||||
in
|
||||
ok @@ restore_mutable_variable return_expr free_vars env
|
||||
else
|
||||
ok @@ O.E_matching {matchee; cases=O.Match_option {match_none=match_none'; match_some=(n,expr',tv)}}
|
||||
return @@ O.e_matching matchee @@ O.Match_option {match_none=match_none'; match_some=(n,expr',tv)}
|
||||
| I.Match_list {match_nil;match_cons} ->
|
||||
let%bind match_nil' = compile_expression match_nil in
|
||||
let (hd,tl,expr,tv) = match_cons in
|
||||
@ -406,17 +437,16 @@ and compile_matching : I.matching -> O.expression_content result =
|
||||
if (List.length free_vars != 0) then
|
||||
let match_expr = O.e_matching matchee (O.Match_list {match_nil; match_cons=(hd,tl,expr,tv)}) in
|
||||
let return_expr = fun expr ->
|
||||
O.E_let_in {let_binder=(env,None); mut=false; inline=false;rhs=(store_mutable_variable free_vars);
|
||||
let_result=O.e_let_in (env,None) false false match_expr @@
|
||||
O.e_let_in (env,None) false false (store_mutable_variable free_vars) @@
|
||||
O.e_let_in (env,None) false false match_expr @@
|
||||
expr
|
||||
}
|
||||
in
|
||||
ok @@ restore_mutable_variable return_expr free_vars env
|
||||
else
|
||||
ok @@ O.E_matching {matchee;cases=O.Match_list {match_nil=match_nil'; match_cons=(hd,tl,expr',tv)}}
|
||||
return @@ O.e_matching matchee @@ O.Match_list {match_nil=match_nil'; match_cons=(hd,tl,expr',tv)}
|
||||
| I.Match_tuple ((lst,expr), tv) ->
|
||||
let%bind expr = compile_expression expr in
|
||||
ok @@ O.E_matching {matchee; cases=O.Match_tuple ((lst,expr), tv)}
|
||||
return @@ O.e_matching matchee @@ O.Match_tuple ((lst,expr), tv)
|
||||
| I.Match_variant (lst,tv) ->
|
||||
let env = Var.fresh () in
|
||||
let aux fv ((c,n),expr) =
|
||||
@ -429,15 +459,14 @@ and compile_matching : I.matching -> O.expression_content result =
|
||||
let free_vars = List.sort_uniq Var.compare @@ List.concat fv in
|
||||
if (List.length free_vars == 0) then (
|
||||
let cases = List.map (fun case -> let (a,_,b) = case in (a,b)) cases in
|
||||
ok @@ O.E_matching{matchee; cases=O.Match_variant (cases,tv)}
|
||||
return @@ O.e_matching matchee @@ O.Match_variant (cases,tv)
|
||||
) else (
|
||||
let cases = List.map (fun case -> let (a,b,_) = case in (a,b)) cases in
|
||||
let match_expr = O.e_matching matchee @@ O.Match_variant (cases,tv) in
|
||||
let return_expr = fun expr ->
|
||||
O.E_let_in {let_binder=(env,None); mut=false; inline=false; rhs=(store_mutable_variable free_vars);
|
||||
let_result=O.e_let_in (env,None) false false match_expr @@
|
||||
O.e_let_in (env,None) false false (store_mutable_variable free_vars) @@
|
||||
O.e_let_in (env,None) false false match_expr @@
|
||||
expr
|
||||
}
|
||||
in
|
||||
ok @@ restore_mutable_variable return_expr free_vars env
|
||||
)
|
||||
@ -469,11 +498,10 @@ and compile_while I.{condition;body} =
|
||||
let loop = O.e_constant C_FOLD_WHILE [aux_func; O.e_variable env_rec] in
|
||||
let let_binder = (env_rec,None) in
|
||||
let return_expr = fun expr ->
|
||||
O.E_let_in {let_binder; mut=false; inline=false; rhs=init_rec; let_result=
|
||||
O.e_let_in let_binder false false init_rec @@
|
||||
O.e_let_in let_binder false false loop @@
|
||||
O.e_let_in let_binder false false (O.e_record_accessor (O.e_variable env_rec) (Label"0")) @@
|
||||
expr
|
||||
}
|
||||
in
|
||||
ok @@ restore_mutable_variable return_expr captured_name_list env_rec
|
||||
|
||||
@ -515,23 +543,23 @@ and compile_for I.{binder;start;final;increment;body} =
|
||||
let%bind start = compile_expression start in
|
||||
let let_binder = (env_rec,None) in
|
||||
let return_expr = fun expr ->
|
||||
O.E_let_in {let_binder=(binder, Some (O.t_int ()));mut=false; inline=false;rhs=start;let_result=
|
||||
O.e_let_in (binder, Some (O.t_int ())) false false start @@
|
||||
O.e_let_in let_binder false false init_rec @@
|
||||
O.e_let_in let_binder false false loop @@
|
||||
O.e_let_in let_binder false false (O.e_record_accessor (O.e_variable env_rec) (Label "0")) @@
|
||||
expr
|
||||
}
|
||||
in
|
||||
ok @@ restore_mutable_variable return_expr captured_name_list env_rec
|
||||
|
||||
and compile_for_each I.{binder;collection;collection_type; body} =
|
||||
let env_rec = Var.fresh () in
|
||||
let args = Var.fresh () in
|
||||
|
||||
let%bind element_names = ok @@ match snd binder with
|
||||
| Some v -> [fst binder;v]
|
||||
| None -> [fst binder]
|
||||
in
|
||||
|
||||
let env = Var.fresh () in
|
||||
let%bind body = compile_expression body in
|
||||
let%bind ((_,free_vars), body) = repair_mutable_variable_in_loops body element_names args in
|
||||
let for_body = add_to_end body @@ (O.e_record_accessor (O.e_variable args) (Label "0")) in
|
||||
@ -555,10 +583,10 @@ and compile_for_each I.{binder;collection;collection_type; body} =
|
||||
| Map -> ok @@ O.C_MAP_FOLD | Set -> ok @@ O.C_SET_FOLD | List -> ok @@ O.C_LIST_FOLD
|
||||
in
|
||||
let fold = fun expr ->
|
||||
O.E_let_in {let_binder=(env,None);mut=false; inline=false;rhs=(O.e_constant op_name [lambda; collect ; init_record]);
|
||||
let_result=expr;}
|
||||
O.e_let_in (env_rec,None) false false (O.e_constant op_name [lambda; collect ; init_record]) expr
|
||||
in
|
||||
ok @@ restore_mutable_variable fold free_vars env
|
||||
ok @@ restore_mutable_variable fold free_vars env_rec
|
||||
|
||||
let compile_declaration : I.declaration Location.wrap -> _ =
|
||||
fun {wrap_content=declaration;location} ->
|
||||
let return decl = ok @@ Location.wrap ~loc:location decl in
|
||||
@ -639,18 +667,18 @@ and uncompile_type_operator : O.type_operator -> I.type_operator result =
|
||||
let%bind (i,o) = bind_map_pair uncompile_type_expression (i,o) in
|
||||
ok @@ I.TC_arrow (i,o)
|
||||
|
||||
let rec uncompile_expression : O.expression -> I.expression result =
|
||||
let rec uncompile_expression' : O.expression -> I.expression result =
|
||||
fun e ->
|
||||
let return expr = ok @@ I.make_e ~loc:e.location expr in
|
||||
match e.expression_content with
|
||||
O.E_literal lit -> return @@ I.E_literal lit
|
||||
| O.E_constant {cons_name;arguments} ->
|
||||
let%bind arguments = bind_map_list uncompile_expression arguments in
|
||||
let%bind arguments = bind_map_list uncompile_expression' arguments in
|
||||
return @@ I.E_constant {cons_name;arguments}
|
||||
| O.E_variable name -> return @@ I.E_variable name
|
||||
| O.E_application {lamb; args} ->
|
||||
let%bind lamb = uncompile_expression lamb in
|
||||
let%bind args = uncompile_expression args in
|
||||
let%bind lamb = uncompile_expression' lamb in
|
||||
let%bind args = uncompile_expression' args in
|
||||
return @@ I.E_application {lamb; args}
|
||||
| O.E_lambda lambda ->
|
||||
let%bind lambda = uncompile_lambda lambda in
|
||||
@ -662,75 +690,75 @@ let rec uncompile_expression : O.expression -> I.expression result =
|
||||
| O.E_let_in {let_binder;inline;rhs;let_result} ->
|
||||
let (binder,ty_opt) = let_binder in
|
||||
let%bind ty_opt = bind_map_option uncompile_type_expression ty_opt in
|
||||
let%bind rhs = uncompile_expression rhs in
|
||||
let%bind let_result = uncompile_expression let_result in
|
||||
let%bind rhs = uncompile_expression' rhs in
|
||||
let%bind let_result = uncompile_expression' let_result in
|
||||
return @@ I.E_let_in {let_binder=(binder,ty_opt);inline;rhs;let_result}
|
||||
| O.E_constructor {constructor;element} ->
|
||||
let%bind element = uncompile_expression element in
|
||||
let%bind element = uncompile_expression' element in
|
||||
return @@ I.E_constructor {constructor;element}
|
||||
| O.E_matching {matchee; cases} ->
|
||||
let%bind matchee = uncompile_expression matchee in
|
||||
let%bind matchee = uncompile_expression' matchee in
|
||||
let%bind cases = uncompile_matching cases in
|
||||
return @@ I.E_matching {matchee;cases}
|
||||
| O.E_record record ->
|
||||
let record = I.LMap.to_kv_list record in
|
||||
let%bind record =
|
||||
bind_map_list (fun (k,v) ->
|
||||
let%bind v = uncompile_expression v in
|
||||
let%bind v = uncompile_expression' v in
|
||||
ok @@ (k,v)
|
||||
) record
|
||||
in
|
||||
return @@ I.E_record (O.LMap.of_list record)
|
||||
| O.E_record_accessor {record;path} ->
|
||||
let%bind record = uncompile_expression record in
|
||||
let%bind record = uncompile_expression' record in
|
||||
return @@ I.E_record_accessor {record;path}
|
||||
| O.E_record_update {record;path;update} ->
|
||||
let%bind record = uncompile_expression record in
|
||||
let%bind update = uncompile_expression update in
|
||||
let%bind record = uncompile_expression' record in
|
||||
let%bind update = uncompile_expression' update in
|
||||
return @@ I.E_record_update {record;path;update}
|
||||
| O.E_tuple tuple ->
|
||||
let%bind tuple = bind_map_list uncompile_expression tuple in
|
||||
let%bind tuple = bind_map_list uncompile_expression' tuple in
|
||||
return @@ I.E_tuple tuple
|
||||
| O.E_tuple_accessor {tuple;path} ->
|
||||
let%bind tuple = uncompile_expression tuple in
|
||||
let%bind tuple = uncompile_expression' tuple in
|
||||
return @@ I.E_tuple_accessor {tuple;path}
|
||||
| O.E_tuple_update {tuple;path;update} ->
|
||||
let%bind tuple = uncompile_expression tuple in
|
||||
let%bind update = uncompile_expression update in
|
||||
let%bind tuple = uncompile_expression' tuple in
|
||||
let%bind update = uncompile_expression' update in
|
||||
return @@ I.E_tuple_update {tuple;path;update}
|
||||
| O.E_map map ->
|
||||
let%bind map = bind_map_list (
|
||||
bind_map_pair uncompile_expression
|
||||
bind_map_pair uncompile_expression'
|
||||
) map
|
||||
in
|
||||
return @@ I.E_map map
|
||||
| O.E_big_map big_map ->
|
||||
let%bind big_map = bind_map_list (
|
||||
bind_map_pair uncompile_expression
|
||||
bind_map_pair uncompile_expression'
|
||||
) big_map
|
||||
in
|
||||
return @@ I.E_big_map big_map
|
||||
| O.E_list lst ->
|
||||
let%bind lst = bind_map_list uncompile_expression lst in
|
||||
let%bind lst = bind_map_list uncompile_expression' lst in
|
||||
return @@ I.E_list lst
|
||||
| O.E_set set ->
|
||||
let%bind set = bind_map_list uncompile_expression set in
|
||||
let%bind set = bind_map_list uncompile_expression' set in
|
||||
return @@ I.E_set set
|
||||
| O.E_look_up look_up ->
|
||||
let%bind look_up = bind_map_pair uncompile_expression look_up in
|
||||
let%bind look_up = bind_map_pair uncompile_expression' look_up in
|
||||
return @@ I.E_look_up look_up
|
||||
| O.E_ascription {anno_expr; type_annotation} ->
|
||||
let%bind anno_expr = uncompile_expression anno_expr in
|
||||
let%bind anno_expr = uncompile_expression' anno_expr in
|
||||
let%bind type_annotation = uncompile_type_expression type_annotation in
|
||||
return @@ I.E_ascription {anno_expr; type_annotation}
|
||||
| O.E_cond {condition;then_clause;else_clause} ->
|
||||
let%bind condition = uncompile_expression condition in
|
||||
let%bind then_clause = uncompile_expression then_clause in
|
||||
let%bind else_clause = uncompile_expression else_clause in
|
||||
let%bind condition = uncompile_expression' condition in
|
||||
let%bind then_clause = uncompile_expression' then_clause in
|
||||
let%bind else_clause = uncompile_expression' else_clause in
|
||||
return @@ I.E_cond {condition; then_clause; else_clause}
|
||||
| O.E_sequence {expr1; expr2} ->
|
||||
let%bind expr1 = uncompile_expression expr1 in
|
||||
let%bind expr2 = uncompile_expression expr2 in
|
||||
let%bind expr1 = uncompile_expression' expr1 in
|
||||
let%bind expr2 = uncompile_expression' expr2 in
|
||||
return @@ I.E_sequence {expr1; expr2}
|
||||
| O.E_skip -> return @@ I.E_skip
|
||||
|
||||
@ -738,32 +766,32 @@ and uncompile_lambda : O.lambda -> I.lambda result =
|
||||
fun {binder;input_type;output_type;result}->
|
||||
let%bind input_type = bind_map_option uncompile_type_expression input_type in
|
||||
let%bind output_type = bind_map_option uncompile_type_expression output_type in
|
||||
let%bind result = uncompile_expression result in
|
||||
let%bind result = uncompile_expression' result in
|
||||
ok @@ I.{binder;input_type;output_type;result}
|
||||
and uncompile_matching : O.matching_expr -> I.matching_expr result =
|
||||
fun m ->
|
||||
match m with
|
||||
| O.Match_bool {match_true;match_false} ->
|
||||
let%bind match_true = uncompile_expression match_true in
|
||||
let%bind match_false = uncompile_expression match_false in
|
||||
let%bind match_true = uncompile_expression' match_true in
|
||||
let%bind match_false = uncompile_expression' match_false in
|
||||
ok @@ I.Match_bool {match_true;match_false}
|
||||
| O.Match_list {match_nil;match_cons} ->
|
||||
let%bind match_nil = uncompile_expression match_nil in
|
||||
let%bind match_nil = uncompile_expression' match_nil in
|
||||
let (hd,tl,expr,tv) = match_cons in
|
||||
let%bind expr = uncompile_expression expr in
|
||||
let%bind expr = uncompile_expression' expr in
|
||||
ok @@ I.Match_list {match_nil; match_cons=(hd,tl,expr,tv)}
|
||||
| O.Match_option {match_none;match_some} ->
|
||||
let%bind match_none = uncompile_expression match_none in
|
||||
let%bind match_none = uncompile_expression' match_none in
|
||||
let (n,expr,tv) = match_some in
|
||||
let%bind expr = uncompile_expression expr in
|
||||
let%bind expr = uncompile_expression' expr in
|
||||
ok @@ I.Match_option {match_none; match_some=(n,expr,tv)}
|
||||
| O.Match_tuple ((lst,expr), tv) ->
|
||||
let%bind expr = uncompile_expression expr in
|
||||
let%bind expr = uncompile_expression' expr in
|
||||
ok @@ O.Match_tuple ((lst,expr), tv)
|
||||
| O.Match_variant (lst,tv) ->
|
||||
let%bind lst = bind_map_list (
|
||||
fun ((c,n),expr) ->
|
||||
let%bind expr = uncompile_expression expr in
|
||||
let%bind expr = uncompile_expression' expr in
|
||||
ok @@ ((c,n),expr)
|
||||
) lst
|
||||
in
|
||||
|
@ -702,9 +702,21 @@ module Typer = struct
|
||||
[i ; j ; s] ()
|
||||
|
||||
let failwith_ = typer_1_opt "FAILWITH" @@ fun t opt ->
|
||||
let%bind () =
|
||||
Assert.assert_true @@
|
||||
(is_t_string t) in
|
||||
let%bind _ =
|
||||
if eq_1 t (t_string ())
|
||||
then ok ()
|
||||
else if eq_1 t (t_nat ())
|
||||
then ok ()
|
||||
else if eq_1 t (t_int ())
|
||||
then ok ()
|
||||
else
|
||||
fail @@ Operator_errors.typeclass_error "Failwith with disallowed type" "failwith"
|
||||
[
|
||||
[t_string()] ;
|
||||
[t_nat()] ;
|
||||
[t_int()] ;
|
||||
]
|
||||
[t] () in
|
||||
let default = t_unit () in
|
||||
ok @@ Simple_utils.Option.unopt ~default opt
|
||||
|
||||
|
@ -118,7 +118,7 @@ let e_lambda ?loc binder input_type output_type result : expression = make_e ?lo
|
||||
let e_recursive ?loc fun_name fun_type lambda = make_e ?loc @@ E_recursive {fun_name; fun_type; lambda}
|
||||
let e_let_in ?loc (binder, ascr) mut inline rhs let_result = make_e ?loc @@ E_let_in { let_binder = (binder, ascr) ; rhs ; let_result; inline; mut }
|
||||
|
||||
let e_constructor ?loc s a : expression = make_e ?loc @@ E_constructor { constructor = Constructor s; element = a}
|
||||
let e_constructor ?loc s a : expression = make_e ?loc @@ E_constructor { constructor = s; element = a}
|
||||
let e_matching ?loc a b : expression = make_e ?loc @@ E_matching {matchee=a;cases=b}
|
||||
|
||||
let e_record ?loc map : expression = make_e ?loc @@ E_record map
|
||||
|
@ -68,7 +68,7 @@ val e_some : ?loc:Location.t -> expression -> expression
|
||||
val e_none : ?loc:Location.t -> unit -> expression
|
||||
|
||||
val e_variable : ?loc:Location.t -> expression_variable -> expression
|
||||
val e_constructor : ?loc:Location.t -> string -> expression -> expression
|
||||
val e_constructor : ?loc:Location.t -> constructor' -> expression -> expression
|
||||
val e_constant : ?loc:Location.t -> constant' -> expression list -> expression
|
||||
|
||||
val e_lambda : ?loc:Location.t -> expression_variable -> type_expression option -> type_expression option -> expression -> expression
|
||||
|
@ -527,3 +527,8 @@ let program_environment (program : program) : full_environment =
|
||||
let last_declaration = Location.unwrap List.(hd @@ rev program) in
|
||||
match last_declaration with
|
||||
| Declaration_constant { binder=_ ; expr=_ ; inline=_ ; post_env } -> post_env
|
||||
|
||||
let equal_variables a b : bool =
|
||||
match a.expression_content, b.expression_content with
|
||||
| E_variable a, E_variable b -> Var.equal a b
|
||||
| _, _ -> false
|
||||
|
@ -10,6 +10,8 @@ val merge_annotation : type_expression option -> type_expression option -> error
|
||||
(* No information about what made it fail *)
|
||||
val type_expression_eq : ( type_expression * type_expression ) -> bool
|
||||
|
||||
val equal_variables : expression -> expression -> bool
|
||||
|
||||
module Free_variables : sig
|
||||
type bindings = expression_variable list
|
||||
|
||||
|
11
src/test/contracts/amount_lambda.mligo
Normal file
11
src/test/contracts/amount_lambda.mligo
Normal file
@ -0,0 +1,11 @@
|
||||
(* should return a constant function *)
|
||||
let f1 (x : unit) : unit -> tez =
|
||||
let amt : tez = Current.amount in
|
||||
fun (x : unit) -> amt
|
||||
|
||||
(* should return an impure function *)
|
||||
let f2 (x : unit) : unit -> tez =
|
||||
fun (x : unit) -> Current.amount
|
||||
|
||||
let main (b,s : bool * (unit -> tez)) : operation list * (unit -> tez) =
|
||||
(([] : operation list), (if b then f1 () else f2 ()))
|
@ -29,7 +29,7 @@ function foobar (const i : int) : int is
|
||||
}
|
||||
else
|
||||
case p of
|
||||
Zero (n) -> failwith ("wooo")
|
||||
Zero (n) -> failwith(42n)
|
||||
| Pos (n) -> skip
|
||||
end
|
||||
} with
|
||||
@ -39,5 +39,5 @@ function foobar (const i : int) : int is
|
||||
end
|
||||
|
||||
function failer (const p : int) : int is block {
|
||||
if p = 1 then failwith ("some_string") else skip
|
||||
if p = 1 then failwith (42) else skip
|
||||
} with p
|
||||
|
2
src/test/contracts/negative/failwith_wrong_type.ligo
Normal file
2
src/test/contracts/negative/failwith_wrong_type.ligo
Normal file
@ -0,0 +1,2 @@
|
||||
|
||||
const bad : unit = failwith((nil : list(int)))
|
8
src/test/contracts/sequence.mligo
Normal file
8
src/test/contracts/sequence.mligo
Normal file
@ -0,0 +1,8 @@
|
||||
let y (_ : unit) : nat =
|
||||
let x : nat = 1n in
|
||||
begin
|
||||
(let x : nat = 2n in unit) ;
|
||||
(let x : nat = 23n in unit) ;
|
||||
(let x : nat = 42n in unit) ;
|
||||
x
|
||||
end
|
@ -1192,6 +1192,10 @@ let condition_religo () : unit result =
|
||||
] in
|
||||
ok ()
|
||||
|
||||
let sequence_mligo () : unit result =
|
||||
let%bind program = mtype_file "./contracts/sequence.mligo" in
|
||||
expect_eq program "y" (e_unit ()) (e_nat 1)
|
||||
|
||||
let eq_bool_common program =
|
||||
let%bind _ =
|
||||
bind_map_list (fun ( a , b , expected ) ->
|
||||
@ -2390,6 +2394,7 @@ let main = test_suite "Integration (End to End)" [
|
||||
test "condition (ligo)" condition ;
|
||||
test "condition (mligo)" condition_mligo ;
|
||||
test "condition (religo)" condition_religo ;
|
||||
test "sequence (mligo" sequence_mligo ;
|
||||
test "eq bool (ligo)" eq_bool ;
|
||||
test "eq bool (mligo)" eq_bool_mligo ;
|
||||
test "eq bool (religo)" eq_bool_religo ;
|
||||
|
8
tools/compact-ligo-ide/.babelrc
Normal file
8
tools/compact-ligo-ide/.babelrc
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"presets": [
|
||||
"@babel/preset-react",
|
||||
"@babel/preset-env",
|
||||
"@babel/preset-typescript"
|
||||
],
|
||||
"plugins": ["@babel/plugin-transform-react-jsx"]
|
||||
}
|
6
tools/compact-ligo-ide/.gitignore
vendored
Normal file
6
tools/compact-ligo-ide/.gitignore
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
*.log
|
||||
|
||||
node_modules/
|
||||
lib/
|
||||
.cache/
|
||||
dist/
|
9
tools/compact-ligo-ide/.npmignore
Normal file
9
tools/compact-ligo-ide/.npmignore
Normal file
@ -0,0 +1,9 @@
|
||||
src
|
||||
demo
|
||||
|
||||
*.lock
|
||||
.babelrc
|
||||
.gitignore
|
||||
webpack.config.js
|
||||
tsconfig.json
|
||||
webpack.config.js
|
194
tools/compact-ligo-ide/README.md
Normal file
194
tools/compact-ligo-ide/README.md
Normal file
@ -0,0 +1,194 @@
|
||||
A React component for embedding Ligo code snippets on a page.
|
||||
|
||||
# Quick start
|
||||
|
||||
1. Install package `yarn add @ligolang/compact-ligo-ide`
|
||||
2. Add `CompactLigoIde` component to a page
|
||||
|
||||
```jsx
|
||||
import { Code, Language } from "@ligolang/compact-ligo-ide";
|
||||
|
||||
const App = () => {
|
||||
const codeWithConfig = `(*_*
|
||||
name: CameLigo Contract
|
||||
dryRun:
|
||||
entrypoint: main
|
||||
parameters: Increment 2
|
||||
storage: 0
|
||||
*_*)
|
||||
// variant defining pseudo multi-entrypoint actions
|
||||
|
||||
type action is
|
||||
| Increment of int
|
||||
| Decrement of int
|
||||
|
||||
function add (const a : int ; const b : int) : int is
|
||||
block { skip } with a + b
|
||||
|
||||
function subtract (const a : int ; const b : int) : int is
|
||||
block { skip } with a - b
|
||||
|
||||
// real entrypoint that re-routes the flow based
|
||||
// on the action provided
|
||||
function main (const p : action ; const s : int) :
|
||||
(list(operation) * int) is
|
||||
block { skip } with ((nil : list(operation)),
|
||||
case p of
|
||||
| Increment(n) -> add(s, n)
|
||||
| Decrement(n) -> subtract(s, n)
|
||||
end)`;
|
||||
|
||||
const editor = {
|
||||
title: 'Smart Contract',
|
||||
language: Language.CameLigo
|
||||
};
|
||||
const compile = {
|
||||
entrypoint: 'main'
|
||||
};
|
||||
const dryRun = {
|
||||
entrypoint: 'main',
|
||||
parameters: 'Increment 1',
|
||||
storage: '0'
|
||||
};
|
||||
const deploy = {
|
||||
entrypoint: 'main',
|
||||
storage: '0'
|
||||
};
|
||||
const evaluateFunction = {
|
||||
entrypoint: 'add',
|
||||
parameters: '5, 3'
|
||||
};
|
||||
|
||||
return <CompactLigoIde
|
||||
theme="light"
|
||||
editor={editor}
|
||||
compile={compile}
|
||||
dryRun={dryRun}
|
||||
deploy={deploy}
|
||||
evaluateFunction={evaluateFunction}>
|
||||
{codeWithConfig}
|
||||
</CompactLigoIde>
|
||||
};
|
||||
```
|
||||
|
||||
3. Apply styling
|
||||
|
||||
```css
|
||||
<style type="text/css">
|
||||
.compactLigoIde {
|
||||
height: 600px;
|
||||
width: 600px;
|
||||
}
|
||||
</style>
|
||||
```
|
||||
|
||||
# Configuration
|
||||
|
||||
Compact Ligo IDE can be configured via component parameters and/or by passing configuration as a child. The example above illustrastes how to do so.
|
||||
|
||||
## Available configuration
|
||||
|
||||
```js
|
||||
interface CompactLigoIdeProps {
|
||||
editor?: Partial<EditorConfig>;
|
||||
compile?: Partial<CompileConfig>;
|
||||
dryRun?: Partial<DryRunConfig>;
|
||||
deploy?: Partial<DeployConfig>;
|
||||
evaluateFunction?: Partial<EvaluateFunctionConfig>;
|
||||
evaluateValue?: Partial<EvaluateValueConfig>;
|
||||
result?: string;
|
||||
webIdeUrl?: string;
|
||||
theme?: "dark" | "light";
|
||||
children?: string;
|
||||
}
|
||||
|
||||
interface EditorConfig {
|
||||
language: Language;
|
||||
code: string;
|
||||
dirty: boolean;
|
||||
title: string;
|
||||
}
|
||||
|
||||
interface CompileConfig {
|
||||
entrypoint: string;
|
||||
}
|
||||
|
||||
interface DryRunConfig {
|
||||
entrypoint: string;
|
||||
parameters: string;
|
||||
storage: string;
|
||||
}
|
||||
|
||||
interface DeployConfig {
|
||||
entrypoint: string;
|
||||
storage: string;
|
||||
}
|
||||
|
||||
interface EvaluateFunctionConfig {
|
||||
entrypoint: string;
|
||||
parameters: string;
|
||||
}
|
||||
|
||||
interface EvaluateValueConfig {
|
||||
entrypoint: string;
|
||||
}
|
||||
```
|
||||
|
||||
Alternatively, the component can be configured by passing the configuration like so:
|
||||
|
||||
```
|
||||
(*_*
|
||||
name: PascaLIGO Contract
|
||||
language: pascaligo
|
||||
compile:
|
||||
entrypoint: main
|
||||
dryRun:
|
||||
entrypoint: main
|
||||
parameters: Increment (1)
|
||||
storage: 0
|
||||
deploy:
|
||||
entrypoint: main
|
||||
storage: 0
|
||||
evaluateValue:
|
||||
entrypoint: ""
|
||||
evaluateFunction:
|
||||
entrypoint: add
|
||||
parameters: (5, 6)
|
||||
*_*)
|
||||
// variant defining pseudo multi-entrypoint actions
|
||||
type action is
|
||||
| Increment of int
|
||||
| Decrement of int
|
||||
|
||||
function add (const a : int ; const b : int) : int is
|
||||
block { skip } with a + b
|
||||
|
||||
function subtract (const a : int ; const b : int) : int is
|
||||
block { skip } with a - b
|
||||
|
||||
// real entrypoint that re-routes the flow based
|
||||
// on the action provided
|
||||
function main (const p : action ; const s : int) :
|
||||
(list(operation) * int) is
|
||||
block { skip } with ((nil : list(operation)),
|
||||
case p of
|
||||
| Increment(n) -> add(s, n)
|
||||
| Decrement(n) -> subtract(s, n)
|
||||
end)
|
||||
```
|
||||
|
||||
# Contribute
|
||||
|
||||
## Starting dev server
|
||||
|
||||
1. Install dependencies with `yarn install`
|
||||
2. Run `yarn start`
|
||||
3. Open http://localhost:1234 in a browser
|
||||
|
||||
## Build package
|
||||
|
||||
Run `yarn build`.
|
||||
|
||||
## Publish package
|
||||
|
||||
Run `npm publish --access=public`.
|
22
tools/compact-ligo-ide/demo/index.html
Normal file
22
tools/compact-ligo-ide/demo/index.html
Normal file
@ -0,0 +1,22 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
|
||||
<title>React TypeScript App</title>
|
||||
<style type="text/css">
|
||||
.compactLigoIde {
|
||||
height: 400px;
|
||||
width: 600px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
<script src="./index.tsx"></script>
|
||||
</body>
|
||||
|
||||
</html>
|
73
tools/compact-ligo-ide/demo/index.tsx
Normal file
73
tools/compact-ligo-ide/demo/index.tsx
Normal file
@ -0,0 +1,73 @@
|
||||
import React, { useState } from 'react';
|
||||
import { render } from 'react-dom';
|
||||
|
||||
import { CompactLigoIde, Language } from '../src';
|
||||
|
||||
const App = () => {
|
||||
const codeWithConfig = `(*_*
|
||||
name: CameLigo Contract
|
||||
dryRun:
|
||||
entrypoint: main
|
||||
parameters: Increment 2
|
||||
storage: 0
|
||||
*_*)
|
||||
// variant defining pseudo multi-entrypoint actions
|
||||
|
||||
type action is
|
||||
| Increment of int
|
||||
| Decrement of int
|
||||
|
||||
function add (const a : int ; const b : int) : int is
|
||||
block { skip } with a + b
|
||||
|
||||
function subtract (const a : int ; const b : int) : int is
|
||||
block { skip } with a - b
|
||||
|
||||
// real entrypoint that re-routes the flow based
|
||||
// on the action provided
|
||||
function main (const p : action ; const s : int) :
|
||||
(list(operation) * int) is
|
||||
block { skip } with ((nil : list(operation)),
|
||||
case p of
|
||||
| Increment(n) -> add(s, n)
|
||||
| Decrement(n) -> subtract(s, n)
|
||||
end)`;
|
||||
|
||||
const editor = {
|
||||
title: 'Smart Contract',
|
||||
language: Language.CameLigo
|
||||
};
|
||||
const compile = {
|
||||
entrypoint: 'main'
|
||||
};
|
||||
const dryRun = {
|
||||
entrypoint: 'main',
|
||||
parameters: 'Increment 1',
|
||||
storage: '0'
|
||||
};
|
||||
const deploy = {
|
||||
entrypoint: 'main',
|
||||
storage: '0'
|
||||
};
|
||||
const evaluateFunction = {
|
||||
entrypoint: 'add',
|
||||
parameters: '5, 3'
|
||||
};
|
||||
|
||||
const [theme, setTheme] = useState('light');
|
||||
|
||||
return <>
|
||||
<button onClick={() => theme === 'light' ? setTheme('dark') : setTheme('light')}>Toggle Theme</button>
|
||||
<CompactLigoIde
|
||||
theme={theme}
|
||||
editor={editor}
|
||||
compile={compile}
|
||||
dryRun={dryRun}
|
||||
deploy={deploy}
|
||||
evaluateFunction={evaluateFunction}>
|
||||
{codeWithConfig}
|
||||
</CompactLigoIde>
|
||||
</>;
|
||||
};
|
||||
|
||||
render(<App />, document.getElementById("root"));
|
55
tools/compact-ligo-ide/package.json
Normal file
55
tools/compact-ligo-ide/package.json
Normal file
@ -0,0 +1,55 @@
|
||||
{
|
||||
"name": "@ligolang/compact-ligo-ide",
|
||||
"version": "3.0.3",
|
||||
"main": "./lib/index.js",
|
||||
"scripts": {
|
||||
"start": "parcel ./demo/index.html",
|
||||
"build": "webpack"
|
||||
},
|
||||
"typings": "./typings/index.d.ts",
|
||||
"files": [
|
||||
"lib",
|
||||
"typings/index.d.ts"
|
||||
],
|
||||
"license": "ISC",
|
||||
"peerDependencies": {
|
||||
"react": "^16.13.1",
|
||||
"react-dom": "^16.13.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/cli": "^7.8.4",
|
||||
"@babel/core": "^7.8.7",
|
||||
"@babel/plugin-transform-react-jsx": "^7.8.3",
|
||||
"@babel/preset-env": "^7.8.7",
|
||||
"@babel/preset-react": "^7.8.3",
|
||||
"@babel/preset-typescript": "^7.8.3",
|
||||
"@types/node": "^13.9.5",
|
||||
"@types/react": "^16.9.23",
|
||||
"@types/react-dom": "^16.9.5",
|
||||
"@types/styled-components": "^5.0.1",
|
||||
"babel-loader": "8.0.6",
|
||||
"css-loader": "^3.4.2",
|
||||
"parcel-bundler": "^1.12.4",
|
||||
"path": "^0.12.7",
|
||||
"react": "^16.13.1",
|
||||
"react-dom": "^16.13.1",
|
||||
"style-loader": "^1.1.3",
|
||||
"typescript": "^3.8.3",
|
||||
"webpack": "4.41.5",
|
||||
"webpack-cli": "^3.3.11",
|
||||
"webpack-node-externals": "^1.7.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"@fortawesome/fontawesome-svg-core": "^1.2.28",
|
||||
"@fortawesome/free-solid-svg-icons": "^5.13.0",
|
||||
"@fortawesome/react-fontawesome": "^0.1.9",
|
||||
"@types/react-helmet": "^5.0.15",
|
||||
"@types/styled-theming": "^2.2.2",
|
||||
"axios": "^0.19.2",
|
||||
"monaco-editor": "npm:@ligolang/monaco-editor@0.18.1",
|
||||
"react-helmet": "^5.2.1",
|
||||
"styled-components": "^5.0.1",
|
||||
"styled-theming": "^2.2.0",
|
||||
"yaml": "^1.9.2"
|
||||
}
|
||||
}
|
145
tools/compact-ligo-ide/src/components/compact-ligo-ide.tsx
Normal file
145
tools/compact-ligo-ide/src/components/compact-ligo-ide.tsx
Normal file
@ -0,0 +1,145 @@
|
||||
import axios from 'axios';
|
||||
import React from 'react';
|
||||
import styled, { ThemeProvider } from 'styled-components';
|
||||
import { faExternalLinkAlt } from '@fortawesome/free-solid-svg-icons';
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||
|
||||
import { Editor } from './editor';
|
||||
import { CompactLigoIdeProps, DEFAULT_COMPACT_LIGO_IDE_PROPS, ShareParams } from '../types';
|
||||
import YAML from 'yaml';
|
||||
|
||||
const Container = styled.div`
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
`;
|
||||
|
||||
const Button = styled.div`
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
cursor: pointer;
|
||||
position: absolute;
|
||||
width: 60px;
|
||||
height: 30px;
|
||||
top: 0;
|
||||
right: 0;
|
||||
z-index: 1;
|
||||
padding: 5px;
|
||||
color: white;
|
||||
|
||||
:hover {
|
||||
background: #fc683a;
|
||||
}
|
||||
`;
|
||||
|
||||
const Icon = styled(FontAwesomeIcon)`
|
||||
pointer-events: none;
|
||||
margin-left: 3px;
|
||||
`;
|
||||
|
||||
const OutputContainer = styled.div`
|
||||
position: relative;
|
||||
`;
|
||||
|
||||
const Output = styled.pre`
|
||||
background-color: rgba(14, 116, 255, 1);
|
||||
color: white;
|
||||
padding: 20px;
|
||||
margin: 0;
|
||||
overflow: auto;
|
||||
max-height: 200px;
|
||||
`;
|
||||
|
||||
function parseConfig(content: string): CompactLigoIdeProps {
|
||||
const METADATA_REGEX = /\(\*_\*([^]*?)\*_\*\)\s*/;
|
||||
const match = content.match(METADATA_REGEX);
|
||||
|
||||
if (!match || !match[1]) {
|
||||
return { editor: { code: content } };
|
||||
}
|
||||
|
||||
try {
|
||||
const config = YAML.parse(match[1]);
|
||||
|
||||
return {
|
||||
editor: {
|
||||
title: config.name,
|
||||
language: config.language,
|
||||
code: content.replace(METADATA_REGEX, '')
|
||||
},
|
||||
compile: { ...config.compile },
|
||||
dryRun: { ...config.dryRun },
|
||||
deploy: { ...config.deploy },
|
||||
evaluateFunction: { ...config.evaluateFunction },
|
||||
evaluateValue: { ...config.evaluateValue }
|
||||
};
|
||||
} catch (ex) {
|
||||
throw new Error(`Unable to parse configuration.`);
|
||||
}
|
||||
}
|
||||
|
||||
export function CompactLigoIde(props: CompactLigoIdeProps) {
|
||||
const yamlConfig = props.children ? parseConfig(props.children) : {};
|
||||
|
||||
const shareParams: ShareParams = {
|
||||
editor: {
|
||||
...DEFAULT_COMPACT_LIGO_IDE_PROPS.editor,
|
||||
...yamlConfig.editor,
|
||||
...props.editor
|
||||
},
|
||||
compile: {
|
||||
...DEFAULT_COMPACT_LIGO_IDE_PROPS.compile,
|
||||
...yamlConfig.compile,
|
||||
...props.compile
|
||||
},
|
||||
dryRun: {
|
||||
...DEFAULT_COMPACT_LIGO_IDE_PROPS.dryRun,
|
||||
...yamlConfig.dryRun,
|
||||
...props.dryRun
|
||||
},
|
||||
deploy: {
|
||||
...DEFAULT_COMPACT_LIGO_IDE_PROPS.deploy,
|
||||
...yamlConfig.deploy,
|
||||
...props.deploy
|
||||
},
|
||||
evaluateFunction: {
|
||||
...DEFAULT_COMPACT_LIGO_IDE_PROPS.evaluateFunction,
|
||||
...yamlConfig.evaluateFunction,
|
||||
...props.evaluateFunction
|
||||
},
|
||||
evaluateValue: {
|
||||
...DEFAULT_COMPACT_LIGO_IDE_PROPS.evaluateValue,
|
||||
...yamlConfig.evaluateValue,
|
||||
...props.evaluateValue
|
||||
}
|
||||
};
|
||||
const result = props.result || DEFAULT_COMPACT_LIGO_IDE_PROPS.result;
|
||||
const webIdeUrl = props.webIdeUrl || DEFAULT_COMPACT_LIGO_IDE_PROPS.webIdeUrl;
|
||||
const theme = props.theme || DEFAULT_COMPACT_LIGO_IDE_PROPS.theme;
|
||||
|
||||
async function openInIde() {
|
||||
const response = await axios.post(`${webIdeUrl}/api/share`, { ...shareParams });
|
||||
const { hash } = await response.data;
|
||||
|
||||
window.open(`${webIdeUrl}/p/${hash}`, "_blank");
|
||||
}
|
||||
|
||||
return (
|
||||
<ThemeProvider theme={{ mode: theme }}>
|
||||
<Container className="compactLigoIde">
|
||||
<Editor
|
||||
value={shareParams.editor.code}
|
||||
language={shareParams.editor.language}
|
||||
></Editor>
|
||||
<OutputContainer>
|
||||
<Output>{result}</Output>
|
||||
<Button onClick={openInIde} title="Open in Ligo Web IDE">
|
||||
<span>IDE<Icon icon={faExternalLinkAlt} /></span>
|
||||
</Button>
|
||||
</OutputContainer>
|
||||
</Container>
|
||||
</ThemeProvider>
|
||||
);
|
||||
};
|
83
tools/compact-ligo-ide/src/components/editor.tsx
Normal file
83
tools/compact-ligo-ide/src/components/editor.tsx
Normal file
@ -0,0 +1,83 @@
|
||||
import * as monaco from 'monaco-editor';
|
||||
import React, { useEffect, useRef, useState } from 'react';
|
||||
import { Helmet } from 'react-helmet';
|
||||
import styled, { withTheme } from 'styled-components';
|
||||
|
||||
const Container = styled.div`
|
||||
flex: 2;
|
||||
`;
|
||||
|
||||
export const Editor = withTheme(
|
||||
(props: {
|
||||
value: string;
|
||||
language?: string;
|
||||
onChange?: (value: string) => void;
|
||||
theme: { mode: string };
|
||||
}) => {
|
||||
let containerRef = useRef(null);
|
||||
const isLightTheme = props.theme.mode === 'light';
|
||||
const background = isLightTheme ? "#eff7ff" : "#3b454e40";
|
||||
const lineHighlightBackground = isLightTheme ? "#cee3ff" : "#63768840";
|
||||
const lineNumberColor = "#888";
|
||||
|
||||
const model = monaco.editor.createModel(props.value, props.language);
|
||||
|
||||
monaco.editor.defineTheme("ligoTheme", {
|
||||
base: "vs",
|
||||
inherit: true,
|
||||
rules: [],
|
||||
colors: {
|
||||
"editor.background": background,
|
||||
"editor.lineHighlightBackground": lineHighlightBackground,
|
||||
"editorLineNumber.foreground": lineNumberColor
|
||||
}
|
||||
});
|
||||
|
||||
monaco.editor.setTheme("ligoTheme");
|
||||
|
||||
useEffect(() => {
|
||||
const cleanupFunc: Array<() => void> = [];
|
||||
const htmlElement = (containerRef.current as unknown) as HTMLElement;
|
||||
|
||||
const editor = monaco.editor.create(htmlElement, {
|
||||
readOnly: true,
|
||||
model: model,
|
||||
automaticLayout: true,
|
||||
minimap: {
|
||||
enabled: false
|
||||
}
|
||||
});
|
||||
|
||||
const { dispose } = editor.onDidChangeModelContent(() => {
|
||||
if (props.onChange) {
|
||||
props.onChange(editor.getValue());
|
||||
}
|
||||
});
|
||||
|
||||
cleanupFunc.push(dispose);
|
||||
|
||||
return function cleanUp() {
|
||||
cleanupFunc.forEach(f => f());
|
||||
};
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<Container ref={containerRef}>
|
||||
<Helmet>
|
||||
<style type="text/css">
|
||||
{`
|
||||
.monaco-editor .current-line ~ .line-numbers {
|
||||
color: ${lineNumberColor};
|
||||
}
|
||||
|
||||
.monaco-editor .margin-view-overlays .current-line,
|
||||
.monaco-editor .view-overlays .current-line {
|
||||
background-color: ${lineHighlightBackground};
|
||||
}
|
||||
`}
|
||||
</style>
|
||||
</Helmet>
|
||||
</Container>
|
||||
);
|
||||
}
|
||||
);
|
2
tools/compact-ligo-ide/src/index.tsx
Normal file
2
tools/compact-ligo-ide/src/index.tsx
Normal file
@ -0,0 +1,2 @@
|
||||
export { CompactLigoIde } from './components/compact-ligo-ide';
|
||||
export * from './types';
|
105
tools/compact-ligo-ide/src/types.ts
Normal file
105
tools/compact-ligo-ide/src/types.ts
Normal file
@ -0,0 +1,105 @@
|
||||
export enum Language {
|
||||
PascaLigo = 'pascaligo',
|
||||
CameLigo = 'cameligo',
|
||||
ReasonLigo = 'reasonligo'
|
||||
};
|
||||
|
||||
export interface ShareParams {
|
||||
editor: EditorConfig;
|
||||
compile: CompileConfig;
|
||||
dryRun: DryRunConfig;
|
||||
deploy: DeployConfig;
|
||||
evaluateFunction: EvaluateFunctionConfig;
|
||||
evaluateValue: EvaluateValueConfig;
|
||||
}
|
||||
|
||||
export interface EditorConfig {
|
||||
language: Language;
|
||||
code: string;
|
||||
dirty: boolean;
|
||||
title: string;
|
||||
}
|
||||
|
||||
export interface CompileConfig {
|
||||
entrypoint: string;
|
||||
}
|
||||
|
||||
export interface DryRunConfig {
|
||||
entrypoint: string;
|
||||
parameters: string;
|
||||
storage: string;
|
||||
}
|
||||
|
||||
export interface DeployConfig {
|
||||
entrypoint: string;
|
||||
storage: string;
|
||||
}
|
||||
|
||||
export interface EvaluateFunctionConfig {
|
||||
entrypoint: string;
|
||||
parameters: string;
|
||||
}
|
||||
|
||||
export interface EvaluateValueConfig {
|
||||
entrypoint: string;
|
||||
}
|
||||
|
||||
export interface CompactLigoIdeProps {
|
||||
editor?: Partial<EditorConfig>;
|
||||
compile?: Partial<CompileConfig>;
|
||||
dryRun?: Partial<DryRunConfig>;
|
||||
deploy?: Partial<DeployConfig>;
|
||||
evaluateFunction?: Partial<EvaluateFunctionConfig>;
|
||||
evaluateValue?: Partial<EvaluateValueConfig>;
|
||||
result?: string;
|
||||
webIdeUrl?: string;
|
||||
theme?: "dark" | "light";
|
||||
children?: string;
|
||||
}
|
||||
|
||||
export const DEFAULT_EDITOR_CONFIG: EditorConfig = {
|
||||
code: "",
|
||||
language: Language.PascaLigo,
|
||||
dirty: true,
|
||||
title: ""
|
||||
};
|
||||
|
||||
export const DEFAULT_COMPILE_CONFIG: CompileConfig = {
|
||||
entrypoint: ""
|
||||
};
|
||||
|
||||
export const DEFAULT_DRY_RUN_CONFIG: DryRunConfig = {
|
||||
entrypoint: "",
|
||||
parameters: "",
|
||||
storage: ""
|
||||
};
|
||||
|
||||
export const DEFAULT_DEPLOY_CONFIG: DeployConfig = {
|
||||
entrypoint: "",
|
||||
storage: ""
|
||||
};
|
||||
|
||||
export const DEFAULT_EVALUATE_FUNCTION_CONFIG: EvaluateFunctionConfig = {
|
||||
entrypoint: "",
|
||||
parameters: ""
|
||||
};
|
||||
|
||||
export const DEFAULT_EVALUATE_VALUE_CONFIG: EvaluateValueConfig = {
|
||||
entrypoint: ""
|
||||
};
|
||||
|
||||
export const DEFAULT_SHARE_PARAMS: ShareParams = {
|
||||
editor: DEFAULT_EDITOR_CONFIG,
|
||||
compile: DEFAULT_COMPILE_CONFIG,
|
||||
dryRun: DEFAULT_DRY_RUN_CONFIG,
|
||||
deploy: DEFAULT_DEPLOY_CONFIG,
|
||||
evaluateFunction: DEFAULT_EVALUATE_FUNCTION_CONFIG,
|
||||
evaluateValue: DEFAULT_EVALUATE_VALUE_CONFIG
|
||||
};
|
||||
|
||||
export const DEFAULT_COMPACT_LIGO_IDE_PROPS: (ShareParams & CompactLigoIdeProps) = {
|
||||
...DEFAULT_SHARE_PARAMS,
|
||||
result: '',
|
||||
webIdeUrl: process.env.NODE_ENV === 'production' ? 'https://ide.ligolang.org' : 'http://localhost:8080',
|
||||
theme: 'light'
|
||||
};
|
19
tools/compact-ligo-ide/tsconfig.json
Normal file
19
tools/compact-ligo-ide/tsconfig.json
Normal file
@ -0,0 +1,19 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "es5",
|
||||
"lib": ["dom", "dom.iterable", "esnext"],
|
||||
"allowJs": true,
|
||||
"skipLibCheck": true,
|
||||
"esModuleInterop": true,
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"strict": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"module": "esnext",
|
||||
"moduleResolution": "node",
|
||||
"resolveJsonModule": true,
|
||||
"isolatedModules": true,
|
||||
"noEmit": true,
|
||||
"jsx": "react"
|
||||
},
|
||||
"include": ["src"]
|
||||
}
|
5
tools/compact-ligo-ide/typings/index.d.ts
vendored
Normal file
5
tools/compact-ligo-ide/typings/index.d.ts
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
import { StatelessComponent } from 'react';
|
||||
|
||||
declare const Boilerplate: StatelessComponent;
|
||||
|
||||
export { Boilerplate };
|
29
tools/compact-ligo-ide/webpack.config.js
Normal file
29
tools/compact-ligo-ide/webpack.config.js
Normal file
@ -0,0 +1,29 @@
|
||||
const path = require('path');
|
||||
const nodeExternals = require("webpack-node-externals");
|
||||
|
||||
module.exports = {
|
||||
mode: 'production',
|
||||
entry: './src/index.tsx',
|
||||
output: {
|
||||
path: path.resolve('lib'),
|
||||
filename: 'index.js',
|
||||
libraryTarget: 'commonjs2'
|
||||
},
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /\.(t|j)sx?$/,
|
||||
exclude: /(node_modules)/,
|
||||
use: 'babel-loader'
|
||||
},
|
||||
{
|
||||
test: /\.css$/,
|
||||
use: ["style-loader", "css-loader"],
|
||||
},
|
||||
]
|
||||
},
|
||||
externals: [nodeExternals()],
|
||||
resolve: {
|
||||
extensions: ['.ts', '.tsx', '.js', '.jsx']
|
||||
},
|
||||
}
|
6593
tools/compact-ligo-ide/yarn.lock
Normal file
6593
tools/compact-ligo-ide/yarn.lock
Normal file
File diff suppressed because it is too large
Load Diff
27
tools/webide/packages/client/public/circle.svg
Normal file
27
tools/webide/packages/client/public/circle.svg
Normal file
@ -0,0 +1,27 @@
|
||||
<svg width="180" height="180" viewBox="0 0 180 180" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<mask id="mask0" mask-type="alpha" maskUnits="userSpaceOnUse" x="0" y="0" width="180" height="180">
|
||||
<path d="M180 90C180 139.706 139.706 180 90 180C40.2944 180 0 139.706 0 90C0 40.2944 40.2944 0 90 0C139.706 0 180 40.2944 180 90Z" fill="#C4C4C4"/>
|
||||
</mask>
|
||||
<g mask="url(#mask0)">
|
||||
<path d="M0 0H89.8213C139.625 0 179.998 40.3736 179.998 90.1769V180H0V0Z" fill="#3AA0FF"/>
|
||||
<mask id="mask1" mask-type="alpha" maskUnits="userSpaceOnUse" x="0" y="0" width="180" height="180">
|
||||
<path d="M0 0H89.8213C139.625 0 179.998 40.3736 179.998 90.1769V180H0V0Z" fill="#C4C4C4"/>
|
||||
</mask>
|
||||
<g mask="url(#mask1)">
|
||||
<path d="M-97.3224 277.21L218.678 -38.7931L358.935 101.465L42.934 417.468L-97.3224 277.21Z" fill="#2888FF"/>
|
||||
</g>
|
||||
<path d="M63.2759 116.724V0H0V116.724V180H63.2759H179.998V116.724H63.2759Z" fill="#0E74FF"/>
|
||||
<mask id="mask2" mask-type="alpha" maskUnits="userSpaceOnUse" x="0" y="0" width="180" height="180">
|
||||
<path d="M63.2759 116.724V0H0V116.724V180H63.2759H179.998V116.724H63.2759Z" fill="black"/>
|
||||
</mask>
|
||||
<g mask="url(#mask2)">
|
||||
<path d="M-77.562 257.039L238.438 -58.9644L378.695 81.2934L62.6944 397.297L-77.562 257.039Z" fill="#0540FF"/>
|
||||
</g>
|
||||
<mask id="mask3" mask-type="alpha" maskUnits="userSpaceOnUse" x="90" y="0" width="90" height="91">
|
||||
<path d="M90.0007 0.000366211C139.706 0.000366211 180 40.2952 180 90.0004H90.0007V0.000366211Z" fill="#AAA4A4"/>
|
||||
</mask>
|
||||
<g mask="url(#mask3)">
|
||||
<path d="M125.584 -44.9172H224.893V54.3931H125.584V-44.9172Z" fill="#B4DBFF"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 1.5 KiB |
@ -2,7 +2,7 @@
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<link rel="icon" href="%PUBLIC_URL%/logo.svg" />
|
||||
<link rel="icon" href="%PUBLIC_URL%/circle.svg" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<meta name="theme-color" content="#000000" />
|
||||
<meta name="description" content="The LIGO Playground for learning LIGO" />
|
||||
|
File diff suppressed because one or more lines are too long
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 4.1 KiB |
@ -1,13 +1,14 @@
|
||||
import React from 'react';
|
||||
import styled, { css } from 'styled-components';
|
||||
import styled from 'styled-components';
|
||||
|
||||
const Container = styled.div`
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
|
||||
padding: 0.2em 1em;
|
||||
padding: 0.5em 1em;
|
||||
font-family: 'DM Sans', 'Open Sans', sans-serif;
|
||||
|
||||
box-shadow: 0px 1px 1px 0px rgba(0, 0, 0, 0.3);
|
||||
`;
|
||||
|
||||
@ -16,42 +17,27 @@ const Group = styled.div`
|
||||
align-items: center;
|
||||
`;
|
||||
|
||||
const Logo = styled.div`
|
||||
font-size: 1.25em;
|
||||
const Logo = styled.img`
|
||||
height: 32px;
|
||||
`;
|
||||
|
||||
const Link = styled.a`
|
||||
text-decoration: none;
|
||||
color: black;
|
||||
padding: 0.5em 1em;
|
||||
padding: 0em 1em;
|
||||
|
||||
&:hover {
|
||||
color: #3aa0ff;
|
||||
color: #0e74ff;
|
||||
}
|
||||
|
||||
${(props: { versionStyle?: boolean }) =>
|
||||
props.versionStyle &&
|
||||
css`
|
||||
background-color: #efefef;
|
||||
font-weight: 600;
|
||||
margin-left: 3em;
|
||||
|
||||
&:hover {
|
||||
color: black;
|
||||
}
|
||||
`}
|
||||
`;
|
||||
|
||||
export const HeaderComponent = () => {
|
||||
return (
|
||||
<Container>
|
||||
<Group>
|
||||
<Link href="https://ligolang.org">
|
||||
<Logo>LIGO</Logo>
|
||||
</Link>
|
||||
<Link versionStyle href="https://ligolang.org/versions">
|
||||
next
|
||||
</Link>
|
||||
<a href="https://ligolang.org">
|
||||
<Logo src="logo.svg" />
|
||||
</a>
|
||||
</Group>
|
||||
<Group>
|
||||
<Link href="https://ligolang.org/docs/intro/installation">Docs</Link>
|
||||
|
@ -12,8 +12,10 @@ import generateCommand, { GenerateCommandState } from './generate-command';
|
||||
import loading, { LoadingState } from './loading';
|
||||
import result, { ResultState } from './result';
|
||||
import share, { ShareState } from './share';
|
||||
import version, { VersionState } from './version';
|
||||
|
||||
export interface AppState {
|
||||
version: VersionState;
|
||||
editor: EditorState;
|
||||
share: ShareState;
|
||||
compile: CompileState;
|
||||
@ -40,5 +42,6 @@ export default combineReducers({
|
||||
result,
|
||||
command,
|
||||
examples,
|
||||
loading
|
||||
loading,
|
||||
version
|
||||
});
|
||||
|
13
tools/webide/packages/client/src/redux/version.ts
Normal file
13
tools/webide/packages/client/src/redux/version.ts
Normal file
@ -0,0 +1,13 @@
|
||||
export interface VersionState {
|
||||
revision: string;
|
||||
branch: string;
|
||||
}
|
||||
|
||||
const DEFAULT_STATE: VersionState = {
|
||||
revision: 'dev',
|
||||
branch: 'dev'
|
||||
};
|
||||
|
||||
export default (state = DEFAULT_STATE): VersionState => {
|
||||
return state;
|
||||
};
|
86
tools/webide/packages/server/package-lock.json
generated
86
tools/webide/packages/server/package-lock.json
generated
@ -650,6 +650,15 @@
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"@types/cors": {
|
||||
"version": "2.8.6",
|
||||
"resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.6.tgz",
|
||||
"integrity": "sha512-invOmosX0DqbpA+cE2yoHGUlF/blyf7nB0OGYBBiH27crcVm5NmFaZkLP4Ta1hGaesckCi5lVLlydNJCxkTOSg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/express": "*"
|
||||
}
|
||||
},
|
||||
"@types/express": {
|
||||
"version": "4.17.3",
|
||||
"resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.3.tgz",
|
||||
@ -752,12 +761,14 @@
|
||||
"@types/node": {
|
||||
"version": "10.14.21",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-10.14.21.tgz",
|
||||
"integrity": "sha512-nuFlRdBiqbF+PJIEVxm2jLFcQWN7q7iWEJGsBV4n7v1dbI9qXB8im2pMMKMCUZe092sQb5SQft2DHfuQGK5hqQ=="
|
||||
"integrity": "sha512-nuFlRdBiqbF+PJIEVxm2jLFcQWN7q7iWEJGsBV4n7v1dbI9qXB8im2pMMKMCUZe092sQb5SQft2DHfuQGK5hqQ==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/node-fetch": {
|
||||
"version": "2.5.5",
|
||||
"resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.5.5.tgz",
|
||||
"integrity": "sha512-IWwjsyYjGw+em3xTvWVQi5MgYKbRs0du57klfTaZkv/B24AEQ/p/IopNeqIYNy3EsfHOpg8ieQSDomPcsYMHpA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/node": "*",
|
||||
"form-data": "^3.0.0"
|
||||
@ -1056,7 +1067,8 @@
|
||||
"asynckit": {
|
||||
"version": "0.4.0",
|
||||
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
|
||||
"integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k="
|
||||
"integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=",
|
||||
"dev": true
|
||||
},
|
||||
"atob": {
|
||||
"version": "2.1.2",
|
||||
@ -1225,6 +1237,11 @@
|
||||
"file-uri-to-path": "1.0.0"
|
||||
}
|
||||
},
|
||||
"bintrees": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/bintrees/-/bintrees-1.0.1.tgz",
|
||||
"integrity": "sha1-DmVcm5wkNeqraL9AJyJtK1WjRSQ="
|
||||
},
|
||||
"bip39": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/bip39/-/bip39-3.0.2.tgz",
|
||||
@ -1672,6 +1689,7 @@
|
||||
"version": "1.0.8",
|
||||
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
|
||||
"integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"delayed-stream": "~1.0.0"
|
||||
}
|
||||
@ -1767,6 +1785,15 @@
|
||||
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
|
||||
"integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac="
|
||||
},
|
||||
"cors": {
|
||||
"version": "2.8.5",
|
||||
"resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz",
|
||||
"integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==",
|
||||
"requires": {
|
||||
"object-assign": "^4",
|
||||
"vary": "^1"
|
||||
}
|
||||
},
|
||||
"create-error-class": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/create-error-class/-/create-error-class-3.0.2.tgz",
|
||||
@ -1965,7 +1992,8 @@
|
||||
"delayed-stream": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
|
||||
"integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk="
|
||||
"integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=",
|
||||
"dev": true
|
||||
},
|
||||
"depd": {
|
||||
"version": "1.1.2",
|
||||
@ -2415,6 +2443,17 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"express-prometheus-middleware": {
|
||||
"version": "0.8.5",
|
||||
"resolved": "https://registry.npmjs.org/express-prometheus-middleware/-/express-prometheus-middleware-0.8.5.tgz",
|
||||
"integrity": "sha512-DhQZzp8RDZYh72zJCIr8/t5wY15hHpNQXAnr7xpuizOk+nolLDTpcqCIdHfkgXOwK/I29tMydiJzX686N6bzyw==",
|
||||
"requires": {
|
||||
"express": "^4.16.3",
|
||||
"prom-client": "^11.1.1",
|
||||
"response-time": "^2.3.2",
|
||||
"url-value-parser": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"express-winston": {
|
||||
"version": "4.0.3",
|
||||
"resolved": "https://registry.npmjs.org/express-winston/-/express-winston-4.0.3.tgz",
|
||||
@ -2646,6 +2685,7 @@
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.0.tgz",
|
||||
"integrity": "sha512-CKMFDglpbMi6PyN+brwB9Q/GOw0eAnsrEZDgcsH5Krhz5Od/haKHAX0NmQfha2zPPz0JpWzA7GJHGSnvCRLWsg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"asynckit": "^0.4.0",
|
||||
"combined-stream": "^1.0.8",
|
||||
@ -5165,6 +5205,11 @@
|
||||
"integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==",
|
||||
"dev": true
|
||||
},
|
||||
"object-assign": {
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
|
||||
"integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM="
|
||||
},
|
||||
"object-copy": {
|
||||
"version": "0.1.0",
|
||||
"resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz",
|
||||
@ -5256,6 +5301,11 @@
|
||||
"ee-first": "1.1.1"
|
||||
}
|
||||
},
|
||||
"on-headers": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz",
|
||||
"integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA=="
|
||||
},
|
||||
"once": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
|
||||
@ -5533,6 +5583,14 @@
|
||||
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
|
||||
"integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag=="
|
||||
},
|
||||
"prom-client": {
|
||||
"version": "11.5.3",
|
||||
"resolved": "https://registry.npmjs.org/prom-client/-/prom-client-11.5.3.tgz",
|
||||
"integrity": "sha512-iz22FmTbtkyL2vt0MdDFY+kWof+S9UB/NACxSn2aJcewtw+EERsen0urSkZ2WrHseNdydsvcxCTAnPcSMZZv4Q==",
|
||||
"requires": {
|
||||
"tdigest": "^0.1.1"
|
||||
}
|
||||
},
|
||||
"prompts": {
|
||||
"version": "2.3.1",
|
||||
"resolved": "https://registry.npmjs.org/prompts/-/prompts-2.3.1.tgz",
|
||||
@ -5879,6 +5937,15 @@
|
||||
"integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=",
|
||||
"dev": true
|
||||
},
|
||||
"response-time": {
|
||||
"version": "2.3.2",
|
||||
"resolved": "https://registry.npmjs.org/response-time/-/response-time-2.3.2.tgz",
|
||||
"integrity": "sha1-/6cbq5UtYvfB1Jt0NDVfvGjf/Fo=",
|
||||
"requires": {
|
||||
"depd": "~1.1.0",
|
||||
"on-headers": "~1.0.1"
|
||||
}
|
||||
},
|
||||
"ret": {
|
||||
"version": "0.1.15",
|
||||
"resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz",
|
||||
@ -6551,6 +6618,14 @@
|
||||
"integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==",
|
||||
"dev": true
|
||||
},
|
||||
"tdigest": {
|
||||
"version": "0.1.1",
|
||||
"resolved": "https://registry.npmjs.org/tdigest/-/tdigest-0.1.1.tgz",
|
||||
"integrity": "sha1-Ljyyw56kSeVdHmzZEReszKRYgCE=",
|
||||
"requires": {
|
||||
"bintrees": "1.0.1"
|
||||
}
|
||||
},
|
||||
"teeny-request": {
|
||||
"version": "6.0.2",
|
||||
"resolved": "https://registry.npmjs.org/teeny-request/-/teeny-request-6.0.2.tgz",
|
||||
@ -7131,6 +7206,11 @@
|
||||
"prepend-http": "^1.0.1"
|
||||
}
|
||||
},
|
||||
"url-value-parser": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/url-value-parser/-/url-value-parser-2.0.1.tgz",
|
||||
"integrity": "sha512-bexECeREBIueboLGM3Y1WaAzQkIn+Tca/Xjmjmfd0S/hFHSCEoFkNh0/D0l9G4K74MkEP/lLFRlYnxX3d68Qgw=="
|
||||
},
|
||||
"use": {
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz",
|
||||
|
@ -19,6 +19,8 @@
|
||||
"@types/node": "10",
|
||||
"@types/tmp": "^0.1.0",
|
||||
"@types/winston": "^2.4.4",
|
||||
"@types/cors": "^2.8.6",
|
||||
"@types/node-fetch": "^2.5.4",
|
||||
"jest": "^24.9.0",
|
||||
"nodemon": "^1.19.3",
|
||||
"ts-jest": "^24.1.0",
|
||||
@ -32,10 +34,11 @@
|
||||
"@google-cloud/storage": "^4.0.0",
|
||||
"@hapi/joi": "^16.1.7",
|
||||
"@taquito/taquito": "^6.1.0-beta.0",
|
||||
"@types/node-fetch": "^2.5.4",
|
||||
"body-parser": "^1.19.0",
|
||||
"cors": "^2.8.5",
|
||||
"escape-html": "^1.0.3",
|
||||
"express": "^4.17.1",
|
||||
"express-prometheus-middleware": "^0.8.5",
|
||||
"express-winston": "^4.0.1",
|
||||
"node-fetch": "^2.6.0",
|
||||
"sanitize-html": "^1.20.1",
|
||||
|
@ -1,3 +1,4 @@
|
||||
import cors from 'cors';
|
||||
import express from 'express';
|
||||
import fs from 'fs';
|
||||
import { dirname, join } from 'path';
|
||||
@ -13,12 +14,26 @@ import { shareHandler } from './handlers/share';
|
||||
import { sharedLinkHandler } from './handlers/shared-link';
|
||||
import { loadDefaultState } from './load-state';
|
||||
import { errorLoggerMiddleware, loggerMiddleware } from './logger';
|
||||
require('./metrics');
|
||||
|
||||
var bodyParser = require('body-parser');
|
||||
var escape = require('escape-html');
|
||||
const bodyParser = require('body-parser');
|
||||
const escape = require('escape-html');
|
||||
const prometheus = require('express-prometheus-middleware');
|
||||
|
||||
const app = express();
|
||||
const port = 8080;
|
||||
const APP_PORT = 8080;
|
||||
|
||||
const metrics = express();
|
||||
const METRICS_PORT = 8081;
|
||||
|
||||
const corsOptions = {
|
||||
origin: [
|
||||
'https://ligolang.org',
|
||||
'http://localhost:3000',
|
||||
'http://localhost:1234'
|
||||
],
|
||||
optionsSuccessStatus: 200
|
||||
};
|
||||
|
||||
const appRootDirectory =
|
||||
process.env['STATIC_ASSETS'] ||
|
||||
@ -27,6 +42,15 @@ const appBundleDirectory = join(appRootDirectory, 'build');
|
||||
|
||||
app.use(bodyParser.json());
|
||||
app.use(loggerMiddleware);
|
||||
app.use(
|
||||
prometheus({
|
||||
metricsPath: '/metrics',
|
||||
collectDefaultMetrics: true,
|
||||
collectDefaultBuckets: true,
|
||||
requestDurationBuckets: [0.5, 0.6, 0.7, 1, 10, 20, 30, 60],
|
||||
metricsApp: metrics
|
||||
})
|
||||
);
|
||||
|
||||
const file = fs.readFileSync(join(appBundleDirectory, 'index.html'));
|
||||
|
||||
@ -46,6 +70,9 @@ app.use('^/$', async (_, res) =>
|
||||
res.send(template(JSON.stringify(await loadDefaultState(appBundleDirectory))))
|
||||
);
|
||||
app.use(express.static(appBundleDirectory));
|
||||
|
||||
app.options('/api/share', cors(corsOptions));
|
||||
|
||||
app.get(
|
||||
`/p/:hash([0-9a-zA-Z\-\_]+)`,
|
||||
sharedLinkHandler(appBundleDirectory, template)
|
||||
@ -54,13 +81,17 @@ app.post('/api/compile-contract', compileContractHandler);
|
||||
app.post('/api/compile-expression', compileExpressionHandler);
|
||||
app.post('/api/compile-storage', compileStorageHandler);
|
||||
app.post('/api/dry-run', dryRunHandler);
|
||||
app.post('/api/share', shareHandler);
|
||||
app.post('/api/share', cors(corsOptions), shareHandler);
|
||||
app.post('/api/evaluate-value', evaluateValueHandler);
|
||||
app.post('/api/run-function', runFunctionHandler);
|
||||
app.post('/api/deploy', deployHandler);
|
||||
|
||||
app.use(errorLoggerMiddleware);
|
||||
|
||||
app.listen(port, () => {
|
||||
console.log(`Listening on: ${port}`);
|
||||
app.listen(APP_PORT, () => {
|
||||
console.log(`API listening on: ${APP_PORT}`);
|
||||
});
|
||||
|
||||
metrics.listen(METRICS_PORT, () => {
|
||||
console.log(`Metrics listening on: ${METRICS_PORT}`);
|
||||
});
|
||||
|
@ -19,6 +19,10 @@ export async function loadDefaultState(appBundleDirectory: string) {
|
||||
);
|
||||
const examplesList = JSON.parse(examples);
|
||||
const defaultState = {
|
||||
version: {
|
||||
branch: process.env['GIT_TAG'],
|
||||
revision: process.env['GIT_COMMIT']
|
||||
},
|
||||
compile: {},
|
||||
dryRun: {},
|
||||
deploy: {},
|
||||
|
7
tools/webide/packages/server/src/metrics.ts
Normal file
7
tools/webide/packages/server/src/metrics.ts
Normal file
@ -0,0 +1,7 @@
|
||||
const client = require('prom-client');
|
||||
const gauge = new client.Gauge({
|
||||
name: 'ligo_webide_build_info',
|
||||
help: 'Ligo Web IDE build info',
|
||||
labelNames: ['branch', 'revision']
|
||||
}).labels(process.env['GIT_TAG'], process.env['GIT_COMMIT']);
|
||||
gauge.set(1);
|
@ -1471,6 +1471,13 @@
|
||||
dependencies:
|
||||
"@types/node" "*"
|
||||
|
||||
"@types/cors@^2.8.6":
|
||||
version "2.8.6"
|
||||
resolved "https://registry.yarnpkg.com/@types/cors/-/cors-2.8.6.tgz#cfaab33c49c15b1ded32f235111ce9123009bd02"
|
||||
integrity sha512-invOmosX0DqbpA+cE2yoHGUlF/blyf7nB0OGYBBiH27crcVm5NmFaZkLP4Ta1hGaesckCi5lVLlydNJCxkTOSg==
|
||||
dependencies:
|
||||
"@types/express" "*"
|
||||
|
||||
"@types/eslint-visitor-keys@^1.0.0":
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/@types/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz#1ee30d79544ca84d68d4b3cdb0af4f205663dd2d"
|
||||
@ -2582,6 +2589,11 @@ binary-extensions@^1.0.0:
|
||||
resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.13.1.tgz#598afe54755b2868a5330d2aff9d4ebb53209b65"
|
||||
integrity sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==
|
||||
|
||||
bintrees@1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/bintrees/-/bintrees-1.0.1.tgz#0e655c9b9c2435eaab68bf4027226d2b55a34524"
|
||||
integrity sha1-DmVcm5wkNeqraL9AJyJtK1WjRSQ=
|
||||
|
||||
bip39@^3.0.2:
|
||||
version "3.0.2"
|
||||
resolved "https://registry.yarnpkg.com/bip39/-/bip39-3.0.2.tgz#2baf42ff3071fc9ddd5103de92e8f80d9257ee32"
|
||||
@ -3491,6 +3503,14 @@ core-util-is@1.0.2, core-util-is@~1.0.0:
|
||||
resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
|
||||
integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=
|
||||
|
||||
cors@^2.8.5:
|
||||
version "2.8.5"
|
||||
resolved "https://registry.yarnpkg.com/cors/-/cors-2.8.5.tgz#eac11da51592dd86b9f06f6e7ac293b3df875d29"
|
||||
integrity sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==
|
||||
dependencies:
|
||||
object-assign "^4"
|
||||
vary "^1"
|
||||
|
||||
cosmiconfig@^5.0.0, cosmiconfig@^5.2.0, cosmiconfig@^5.2.1:
|
||||
version "5.2.1"
|
||||
resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-5.2.1.tgz#040f726809c591e77a17c0a3626ca45b4f168b1a"
|
||||
@ -4013,7 +4033,7 @@ delegates@^1.0.0:
|
||||
resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a"
|
||||
integrity sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=
|
||||
|
||||
depd@~1.1.2:
|
||||
depd@~1.1.0, depd@~1.1.2:
|
||||
version "1.1.2"
|
||||
resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9"
|
||||
integrity sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=
|
||||
@ -4763,6 +4783,16 @@ expect@^24.9.0:
|
||||
jest-message-util "^24.9.0"
|
||||
jest-regex-util "^24.9.0"
|
||||
|
||||
express-prometheus-middleware@^0.8.5:
|
||||
version "0.8.5"
|
||||
resolved "https://registry.yarnpkg.com/express-prometheus-middleware/-/express-prometheus-middleware-0.8.5.tgz#097b2871184e2bba997c5ce6db4eec289b61e192"
|
||||
integrity sha512-DhQZzp8RDZYh72zJCIr8/t5wY15hHpNQXAnr7xpuizOk+nolLDTpcqCIdHfkgXOwK/I29tMydiJzX686N6bzyw==
|
||||
dependencies:
|
||||
express "^4.16.3"
|
||||
prom-client "^11.1.1"
|
||||
response-time "^2.3.2"
|
||||
url-value-parser "^2.0.0"
|
||||
|
||||
express-winston@^4.0.1:
|
||||
version "4.0.1"
|
||||
resolved "https://registry.yarnpkg.com/express-winston/-/express-winston-4.0.1.tgz#98c74d099b9a7fdeedc56eb839c223968bc33990"
|
||||
@ -4771,7 +4801,7 @@ express-winston@^4.0.1:
|
||||
chalk "^2.4.1"
|
||||
lodash "^4.17.10"
|
||||
|
||||
express@^4.16.2, express@^4.17.1:
|
||||
express@^4.16.2, express@^4.16.3, express@^4.17.1:
|
||||
version "4.17.1"
|
||||
resolved "https://registry.yarnpkg.com/express/-/express-4.17.1.tgz#4491fc38605cf51f8629d39c2b5d026f98a4c134"
|
||||
integrity sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==
|
||||
@ -8210,7 +8240,7 @@ oauth-sign@~0.9.0:
|
||||
resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455"
|
||||
integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==
|
||||
|
||||
object-assign@4.1.1, object-assign@^4.0.1, object-assign@^4.1.0, object-assign@^4.1.1:
|
||||
object-assign@4.1.1, object-assign@^4, object-assign@^4.0.1, object-assign@^4.1.0, object-assign@^4.1.1:
|
||||
version "4.1.1"
|
||||
resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
|
||||
integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=
|
||||
@ -8323,7 +8353,7 @@ on-finished@~2.3.0:
|
||||
dependencies:
|
||||
ee-first "1.1.1"
|
||||
|
||||
on-headers@~1.0.2:
|
||||
on-headers@~1.0.1, on-headers@~1.0.2:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/on-headers/-/on-headers-1.0.2.tgz#772b0ae6aaa525c399e489adfad90c403eb3c28f"
|
||||
integrity sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==
|
||||
@ -9504,6 +9534,13 @@ progress@^2.0.0, progress@^2.0.1:
|
||||
resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8"
|
||||
integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==
|
||||
|
||||
prom-client@^11.1.1:
|
||||
version "11.5.3"
|
||||
resolved "https://registry.yarnpkg.com/prom-client/-/prom-client-11.5.3.tgz#5fedfce1083bac6c2b223738e966d0e1643756f8"
|
||||
integrity sha512-iz22FmTbtkyL2vt0MdDFY+kWof+S9UB/NACxSn2aJcewtw+EERsen0urSkZ2WrHseNdydsvcxCTAnPcSMZZv4Q==
|
||||
dependencies:
|
||||
tdigest "^0.1.1"
|
||||
|
||||
promise-inflight@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/promise-inflight/-/promise-inflight-1.0.1.tgz#98472870bf228132fcbdd868129bad12c3c029e3"
|
||||
@ -10291,6 +10328,14 @@ resolve@1.12.0, resolve@1.x, resolve@^1.10.0, resolve@^1.10.1, resolve@^1.11.0,
|
||||
dependencies:
|
||||
path-parse "^1.0.6"
|
||||
|
||||
response-time@^2.3.2:
|
||||
version "2.3.2"
|
||||
resolved "https://registry.yarnpkg.com/response-time/-/response-time-2.3.2.tgz#ffa71bab952d62f7c1d49b7434355fbc68dffc5a"
|
||||
integrity sha1-/6cbq5UtYvfB1Jt0NDVfvGjf/Fo=
|
||||
dependencies:
|
||||
depd "~1.1.0"
|
||||
on-headers "~1.0.1"
|
||||
|
||||
restore-cursor@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-2.0.0.tgz#9f7ee287f82fd326d4fd162923d62129eee0dfaf"
|
||||
@ -11301,6 +11346,13 @@ tar@^4:
|
||||
safe-buffer "^5.1.2"
|
||||
yallist "^3.0.3"
|
||||
|
||||
tdigest@^0.1.1:
|
||||
version "0.1.1"
|
||||
resolved "https://registry.yarnpkg.com/tdigest/-/tdigest-0.1.1.tgz#2e3cb2c39ea449e55d1e6cd91117accca4588021"
|
||||
integrity sha1-Ljyyw56kSeVdHmzZEReszKRYgCE=
|
||||
dependencies:
|
||||
bintrees "1.0.1"
|
||||
|
||||
teeny-request@^5.2.1:
|
||||
version "5.3.0"
|
||||
resolved "https://registry.yarnpkg.com/teeny-request/-/teeny-request-5.3.0.tgz#c80287b5a51a7c25eef2347ff5467c95e07dac5a"
|
||||
@ -11825,6 +11877,11 @@ url-parse@^1.4.3:
|
||||
querystringify "^2.1.1"
|
||||
requires-port "^1.0.0"
|
||||
|
||||
url-value-parser@^2.0.0:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/url-value-parser/-/url-value-parser-2.0.1.tgz#c8179a095ab9ec1f5aa17ca36af5af396b4e95ed"
|
||||
integrity sha512-bexECeREBIueboLGM3Y1WaAzQkIn+Tca/Xjmjmfd0S/hFHSCEoFkNh0/D0l9G4K74MkEP/lLFRlYnxX3d68Qgw==
|
||||
|
||||
url@^0.11.0:
|
||||
version "0.11.0"
|
||||
resolved "https://registry.yarnpkg.com/url/-/url-0.11.0.tgz#3838e97cfc60521eb73c525a8e55bfdd9e2e28f1"
|
||||
@ -11893,7 +11950,7 @@ validate-npm-package-license@^3.0.1:
|
||||
spdx-correct "^3.0.0"
|
||||
spdx-expression-parse "^3.0.0"
|
||||
|
||||
vary@~1.1.2:
|
||||
vary@^1, vary@~1.1.2:
|
||||
version "1.1.2"
|
||||
resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc"
|
||||
integrity sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=
|
||||
|
Loading…
Reference in New Issue
Block a user