From 652372a38f427e6921e5b93a70b412b82653d767 Mon Sep 17 00:00:00 2001 From: Mikerah Date: Thu, 23 Dec 2021 20:13:19 -0500 Subject: [PATCH 01/26] Added examples directory --- examples/README.md | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 examples/README.md diff --git a/examples/README.md b/examples/README.md new file mode 100644 index 0000000..e91e16b --- /dev/null +++ b/examples/README.md @@ -0,0 +1,9 @@ +# Examples + +This folder contains examples of Stoffel applications that you can use to get an understanding of Stoffel Lang. + +## Demo Applications +- HoneyBadgerSwap: A basic Uniswap-liked automated market maker. We provide two version of this: one in which we want the identities of the traders to be known but not the amounts that they trade and another in which we want both the identities and amounts traded hidden. Similarly, for the liquidity providers. +- LMSR-based prediction market: Similar to the HoneyBadgerSwap example, except users bet on outcomes instead of trades that are determined by the logarithmic scoring rule by Hansen. +- An orderbook-based exchange: An exchange that uses an orderbook in order to keep track of buys and sell bids from traders and market makers. +- Auction: A basic double auction example based on the original Sugar Beet Auction \ No newline at end of file From 5849c261e942a19c512504d5fcbf306554d3a48d Mon Sep 17 00:00:00 2001 From: Mikerah Date: Fri, 24 Dec 2021 13:25:42 -0500 Subject: [PATCH 02/26] Basic honeybadgerswap examples in stoffelang --- examples/README.md | 2 +- examples/stoffel/hbs1.stf | 111 ++++++++++++++++++++++++++++++++++++++ examples/stoffel/hbs2.stf | 108 +++++++++++++++++++++++++++++++++++++ 3 files changed, 220 insertions(+), 1 deletion(-) create mode 100644 examples/stoffel/hbs1.stf create mode 100644 examples/stoffel/hbs2.stf diff --git a/examples/README.md b/examples/README.md index e91e16b..c26e565 100644 --- a/examples/README.md +++ b/examples/README.md @@ -3,7 +3,7 @@ This folder contains examples of Stoffel applications that you can use to get an understanding of Stoffel Lang. ## Demo Applications -- HoneyBadgerSwap: A basic Uniswap-liked automated market maker. We provide two version of this: one in which we want the identities of the traders to be known but not the amounts that they trade and another in which we want both the identities and amounts traded hidden. Similarly, for the liquidity providers. +- HoneyBadgerSwap: A basic Uniswap-liked automated market maker. We provide two version of this: one in which we want the identities of the traders to be known but not the amounts that they trade and another in which we want both the identities and amounts traded hidden. Similarly, for the liquidity providers. In both scenarios, the assets are public. - LMSR-based prediction market: Similar to the HoneyBadgerSwap example, except users bet on outcomes instead of trades that are determined by the logarithmic scoring rule by Hansen. - An orderbook-based exchange: An exchange that uses an orderbook in order to keep track of buys and sell bids from traders and market makers. - Auction: A basic double auction example based on the original Sugar Beet Auction \ No newline at end of file diff --git a/examples/stoffel/hbs1.stf b/examples/stoffel/hbs1.stf new file mode 100644 index 0000000..550e831 --- /dev/null +++ b/examples/stoffel/hbs1.stf @@ -0,0 +1,111 @@ +// HBS where we care about the privacy of traders and LPs + +program HoneyBadgerSwap { + struct Pool { + assetAID: int, + assetBID: int, + amountA: sint, + amountB: sint, + k: sint + } + + struct UserData { + userID: sint, + assets: Map + } + + struct LPData { + lpID: sint, + shares: sint, + userData: UserData + } + + storage sint totalShares; + storage Pool pool; + + storage Map userData; + storage Map lpData; + + fn initialize_pool(assetAID: sint, amountA: sint, assetBID: sint, amountB: sint) { + sint k = amountA * amountB; + pool = Pool {assetAID: assetAID, amountA: amountA, assetBID:assetBID, amountB: amountB, k: k}; + } + + // 2 ways to go about implementing this + // 1: inputs are negative to indicate trade direction + pub fn trade(userID: sint, assetA: sint, amountA: sint, assetB, amountB: sint) -> bool { + // Trade A for B + if amountA < 0 { + sint newAmountA = pools[0].amountA + amountA; + sint priceAssetB = pools[0].k / newAmountA; + sint newAmountB = pools[0].amountB - priceAssetB + + userData[userID].assets[assetA] += amountA; + userData[userID].assets[assetB] += amountB; + + pools[0].amountA = newAmountA; + pools[0].amountB = newAmountB; + + return true; + } + + // Trade B for A + if amountA >= 0 { + Same code as above with a sign change + return true + } + return false + } + // Clearly not so intuitive to implement and incur extra costs due to comparisons + + // 2 : Inputs are positive + pub fn trade(amountA: sint, amountB: sint) -> bool { + // But since we don't have an unsigned type (yet), we need to do a check which is expensive + if amountA < 0 or amount B < 0 { + return false; + } + + sint newAmountA = pools[0].amountA - amountA; + sint priceAssetB = pools[0].k / (pools[0].amountA - newAmountA) + sint newAmountB = pools[0].k / priceAssetB + + userData[userID].assets[assetA] -= amountA; + userData[userID].assets[assetB] += amountB; + + pools[0].amountA = newAmountA; + pools[0].amountB = newAmountB; + } + + // Obviously, needs way more input validation. Will be added when we have more details + // about the language for a complete, realistic example. + pub fn addLiquidity(lpID: sint, amountA: sint, maxAmountB: sint) -> sint { + sint tokenBAmount = (amountA * pool.amountB) / pool.amountA; + sint sharesMinted = (amountA * totalShares) / pool.amountA; + + lpData[lpID].shares += sharesMinted; + totalShares += sharesMinted; + + lpData[lpID].userData.amountA += amountA; + lpData[lpID].userData.amountB += amountB; + + pool.amountA += amountA; + pool.amountB += tokenBAmount; + + } + + // Again, missing some basic functionality but does what we need to do for basic ideation on syntax + pub fn removeLiquidity(lpID: sint, shares: sint) { + sint amountA = (shares * pool.amountA) / totalShares; + sint amountB = (shares * pool.amountB) / totalShares; + + lpData[lpID].shares -= shares; + totalShares -= shares; + + lpData[lpID].userData.amountA -= amountA; + lpData[lpID].userData.amountB -= amountB; + + pool.amountA -= amountA; + pool.amountB -= amountB; + } + +} \ No newline at end of file diff --git a/examples/stoffel/hbs2.stf b/examples/stoffel/hbs2.stf new file mode 100644 index 0000000..add62ed --- /dev/null +++ b/examples/stoffel/hbs2.stf @@ -0,0 +1,108 @@ +// HBS where we only care about trader amounts + +program HoneyBadgerSwap { + struct Pool { + assetAID: int, + assetBID: int, + amountA: sint, + amountB: sint + } + + struct UserData { + userID: int, + assets: Map + } + + struct LPData { + lpID: sint, + shares: sint, + userData: UserData + } + + storage Pool pool; + + storage Map userData; + storage Map lpData; + + fn initialize_pool(assetAID: sint, amountA: sint, assetBID: sint, amountB: sint) { + sint k = amountA * amountB; + pool = Pool {assetAID: assetAID, amountA: amountA, assetBID:assetBID, amountB: amountB, k: k}; + } + + // 2 ways to go about implementing this + // 1: inputs are negative to indicate trade direction + pub fn trade(userID: int, assetA: sint, amountA: sint, assetB, amountB: sint) -> bool { + // Trade A for B + if amountA < 0 { + sint newAmountA = pools[0].amountA + amountA; + sint priceAssetB = pools[0].k / newAmountA; + sint newAmountB = pools[0].amountB - priceAssetB + + userData[userID].assets[assetA] += amountA; + userData[userID].assets[assetB] += amountB; + + pools[0].amountA = newAmountA; + pools[0].amountB = newAmountB; + + return true; + } + + // Trade B for A + if amountA >= 0 { + Same code as above with a sign change + return true + } + return false + } + // Clearly not so intuitive to implement and incur extra costs due to comparisons + + // 2 : Inputs are positive + pub fn trade(userID: int, amountA: sint, amountB: sint) -> bool { + if amountA < 0 or amount B < 0 { + return false; + } + + sint newAmountA = pools[0].amountA - amountA; + sint priceAssetB = pools[0].k / (pools[0].amountA - newAmountA) + sint newAmountB = pools[0].k / priceAssetB + + userData[userID].assets[assetA] -= amountA; + userData[userID].assets[assetB] += amountB; + + pools[0].amountA = newAmountA; + pools[0].amountB = newAmountB; + } + + + // Obviously, needs way more input validation. Will be added when we have more details + // about the language for a complete, realistic example. + pub fn addLiquidity(lpID: int, amountA: sint, maxAmountB: sint) -> sint { + sint tokenBAmount = (amountA * pool.amountB) / pool.amountA; + sint sharesMinted = (amountA * totalShares) / pool.amountA; + + lpData[lpID].shares += sharesMinted; + totalShares += sharesMinted; + + lpData[lpID].userData.amountA += amountA; + lpData[lpID].userData.amountB += amountB; + + pool.amountA += amountA; + pool.amountB += tokenBAmount; + + } + + // Again, missing some basic functionality but does what we need to do for basic ideation on syntax + pub fn removeLiquidity(lpID: int, shares: sint) { + sint amountA = (shares * pool.amountA) / totalShares; + sint amountB = (shares * pool.amountB) / totalShares; + + lpData[lpID].shares -= shares; + totalShares -= shares; + + lpData[lpID].userData.amountA -= amountA; + lpData[lpID].userData.amountB -= amountB; + + pool.amountA -= amountA; + pool.amountB -= amountB; + } +} \ No newline at end of file From bbc01a8649c4575e2a13c5a85f12e4dc755a5147 Mon Sep 17 00:00:00 2001 From: Mikerah Date: Sat, 5 Feb 2022 20:29:16 -0500 Subject: [PATCH 03/26] Changed initialized_pool() to constructor() --- examples/stoffel/hbs1.stf | 2 +- examples/stoffel/hbs2.stf | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/stoffel/hbs1.stf b/examples/stoffel/hbs1.stf index 550e831..54d6d46 100644 --- a/examples/stoffel/hbs1.stf +++ b/examples/stoffel/hbs1.stf @@ -26,7 +26,7 @@ program HoneyBadgerSwap { storage Map userData; storage Map lpData; - fn initialize_pool(assetAID: sint, amountA: sint, assetBID: sint, amountB: sint) { + fn constructor(assetAID: sint, amountA: sint, assetBID: sint, amountB: sint) { sint k = amountA * amountB; pool = Pool {assetAID: assetAID, amountA: amountA, assetBID:assetBID, amountB: amountB, k: k}; } diff --git a/examples/stoffel/hbs2.stf b/examples/stoffel/hbs2.stf index add62ed..7e3887a 100644 --- a/examples/stoffel/hbs2.stf +++ b/examples/stoffel/hbs2.stf @@ -24,7 +24,7 @@ program HoneyBadgerSwap { storage Map userData; storage Map lpData; - fn initialize_pool(assetAID: sint, amountA: sint, assetBID: sint, amountB: sint) { + fn constructor(assetAID: sint, amountA: sint, assetBID: sint, amountB: sint) { sint k = amountA * amountB; pool = Pool {assetAID: assetAID, amountA: amountA, assetBID:assetBID, amountB: amountB, k: k}; } From 2e57c4132b7d5355928ff83d8ee30e8b97525342 Mon Sep 17 00:00:00 2001 From: Mikerah Date: Sat, 5 Feb 2022 20:31:10 -0500 Subject: [PATCH 04/26] Made first letter of functions that are exposed i.e. called by a user a capital letter. --- examples/stoffel/hbs1.stf | 8 ++++---- examples/stoffel/hbs2.stf | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/examples/stoffel/hbs1.stf b/examples/stoffel/hbs1.stf index 54d6d46..7ac1b13 100644 --- a/examples/stoffel/hbs1.stf +++ b/examples/stoffel/hbs1.stf @@ -33,7 +33,7 @@ program HoneyBadgerSwap { // 2 ways to go about implementing this // 1: inputs are negative to indicate trade direction - pub fn trade(userID: sint, assetA: sint, amountA: sint, assetB, amountB: sint) -> bool { + pub fn Trade(userID: sint, assetA: sint, amountA: sint, assetB, amountB: sint) -> bool { // Trade A for B if amountA < 0 { sint newAmountA = pools[0].amountA + amountA; @@ -59,7 +59,7 @@ program HoneyBadgerSwap { // Clearly not so intuitive to implement and incur extra costs due to comparisons // 2 : Inputs are positive - pub fn trade(amountA: sint, amountB: sint) -> bool { + pub fn Trade(amountA: sint, amountB: sint) -> bool { // But since we don't have an unsigned type (yet), we need to do a check which is expensive if amountA < 0 or amount B < 0 { return false; @@ -78,7 +78,7 @@ program HoneyBadgerSwap { // Obviously, needs way more input validation. Will be added when we have more details // about the language for a complete, realistic example. - pub fn addLiquidity(lpID: sint, amountA: sint, maxAmountB: sint) -> sint { + pub fn AddLiquidity(lpID: sint, amountA: sint, maxAmountB: sint) -> sint { sint tokenBAmount = (amountA * pool.amountB) / pool.amountA; sint sharesMinted = (amountA * totalShares) / pool.amountA; @@ -94,7 +94,7 @@ program HoneyBadgerSwap { } // Again, missing some basic functionality but does what we need to do for basic ideation on syntax - pub fn removeLiquidity(lpID: sint, shares: sint) { + pub fn RemoveLiquidity(lpID: sint, shares: sint) { sint amountA = (shares * pool.amountA) / totalShares; sint amountB = (shares * pool.amountB) / totalShares; diff --git a/examples/stoffel/hbs2.stf b/examples/stoffel/hbs2.stf index 7e3887a..03e18f8 100644 --- a/examples/stoffel/hbs2.stf +++ b/examples/stoffel/hbs2.stf @@ -31,7 +31,7 @@ program HoneyBadgerSwap { // 2 ways to go about implementing this // 1: inputs are negative to indicate trade direction - pub fn trade(userID: int, assetA: sint, amountA: sint, assetB, amountB: sint) -> bool { + pub fn Trade(userID: int, assetA: sint, amountA: sint, assetB, amountB: sint) -> bool { // Trade A for B if amountA < 0 { sint newAmountA = pools[0].amountA + amountA; @@ -57,7 +57,7 @@ program HoneyBadgerSwap { // Clearly not so intuitive to implement and incur extra costs due to comparisons // 2 : Inputs are positive - pub fn trade(userID: int, amountA: sint, amountB: sint) -> bool { + pub fn Trade(userID: int, amountA: sint, amountB: sint) -> bool { if amountA < 0 or amount B < 0 { return false; } @@ -76,7 +76,7 @@ program HoneyBadgerSwap { // Obviously, needs way more input validation. Will be added when we have more details // about the language for a complete, realistic example. - pub fn addLiquidity(lpID: int, amountA: sint, maxAmountB: sint) -> sint { + pub fn AddLiquidity(lpID: int, amountA: sint, maxAmountB: sint) -> sint { sint tokenBAmount = (amountA * pool.amountB) / pool.amountA; sint sharesMinted = (amountA * totalShares) / pool.amountA; @@ -92,7 +92,7 @@ program HoneyBadgerSwap { } // Again, missing some basic functionality but does what we need to do for basic ideation on syntax - pub fn removeLiquidity(lpID: int, shares: sint) { + pub fn RemoveLiquidity(lpID: int, shares: sint) { sint amountA = (shares * pool.amountA) / totalShares; sint amountB = (shares * pool.amountB) / totalShares; From 8c02830f16c10cf0872ac278e3efbcf471200bf7 Mon Sep 17 00:00:00 2001 From: Mikerah Date: Sat, 5 Feb 2022 20:37:43 -0500 Subject: [PATCH 05/26] Chose option 2 for Trade function. Will need unsigned numbers. --- examples/stoffel/hbs1.stf | 29 +---------------------------- examples/stoffel/hbs2.stf | 29 +---------------------------- 2 files changed, 2 insertions(+), 56 deletions(-) diff --git a/examples/stoffel/hbs1.stf b/examples/stoffel/hbs1.stf index 7ac1b13..0bd2cad 100644 --- a/examples/stoffel/hbs1.stf +++ b/examples/stoffel/hbs1.stf @@ -31,34 +31,7 @@ program HoneyBadgerSwap { pool = Pool {assetAID: assetAID, amountA: amountA, assetBID:assetBID, amountB: amountB, k: k}; } - // 2 ways to go about implementing this - // 1: inputs are negative to indicate trade direction - pub fn Trade(userID: sint, assetA: sint, amountA: sint, assetB, amountB: sint) -> bool { - // Trade A for B - if amountA < 0 { - sint newAmountA = pools[0].amountA + amountA; - sint priceAssetB = pools[0].k / newAmountA; - sint newAmountB = pools[0].amountB - priceAssetB - - userData[userID].assets[assetA] += amountA; - userData[userID].assets[assetB] += amountB; - - pools[0].amountA = newAmountA; - pools[0].amountB = newAmountB; - - return true; - } - - // Trade B for A - if amountA >= 0 { - Same code as above with a sign change - return true - } - return false - } - // Clearly not so intuitive to implement and incur extra costs due to comparisons - - // 2 : Inputs are positive + // Will need to create an unsigned integer type for the language pub fn Trade(amountA: sint, amountB: sint) -> bool { // But since we don't have an unsigned type (yet), we need to do a check which is expensive if amountA < 0 or amount B < 0 { diff --git a/examples/stoffel/hbs2.stf b/examples/stoffel/hbs2.stf index 03e18f8..0bc26db 100644 --- a/examples/stoffel/hbs2.stf +++ b/examples/stoffel/hbs2.stf @@ -29,34 +29,7 @@ program HoneyBadgerSwap { pool = Pool {assetAID: assetAID, amountA: amountA, assetBID:assetBID, amountB: amountB, k: k}; } - // 2 ways to go about implementing this - // 1: inputs are negative to indicate trade direction - pub fn Trade(userID: int, assetA: sint, amountA: sint, assetB, amountB: sint) -> bool { - // Trade A for B - if amountA < 0 { - sint newAmountA = pools[0].amountA + amountA; - sint priceAssetB = pools[0].k / newAmountA; - sint newAmountB = pools[0].amountB - priceAssetB - - userData[userID].assets[assetA] += amountA; - userData[userID].assets[assetB] += amountB; - - pools[0].amountA = newAmountA; - pools[0].amountB = newAmountB; - - return true; - } - - // Trade B for A - if amountA >= 0 { - Same code as above with a sign change - return true - } - return false - } - // Clearly not so intuitive to implement and incur extra costs due to comparisons - - // 2 : Inputs are positive + // Will need to create an unsigned integer type for the language pub fn Trade(userID: int, amountA: sint, amountB: sint) -> bool { if amountA < 0 or amount B < 0 { return false; From 000bcccacd89f018a18ed197e86b0813304e188d Mon Sep 17 00:00:00 2001 From: Mikerah Date: Wed, 16 Mar 2022 20:33:35 -0400 Subject: [PATCH 06/26] Started pest grammar --- compiler/parser/stoffel_lang.pest | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 compiler/parser/stoffel_lang.pest diff --git a/compiler/parser/stoffel_lang.pest b/compiler/parser/stoffel_lang.pest new file mode 100644 index 0000000..15c599a --- /dev/null +++ b/compiler/parser/stoffel_lang.pest @@ -0,0 +1,15 @@ +alpha = {'a'..'z' | 'A'..'Z'} +digit = {'0'..'9'} +ident = { (alpha | digit)+ } +storage_var = {"storage" ~ " " ~ (types | container_types) ~ " " ~ (!digit ~ ident)+ ~ ";"} +types = { "sint" } +container_types = { "Map" ~ "<" ~ (types | ident) ~ "," ~ (types | ident) ~ ">"} + +program_def = { "program" ~ " " ~ (!digit ~ ident)+ ~ " " ~ program_block} +program_block = { "{" ~ "}" } + +struct_def = { "struct" ~ " " ~ (!digit ~ ident)+ ~ " " ~ struct_block } +struct_block = { "{" ~ "}" } + +function_def = { "fn" ~ " " ~ (!digit ~ ident)+ ~ " " ~ function_block } +function_block = { "{" ~ "}" } \ No newline at end of file From d650663aadcf5392e3583afa2ad910f78affe199 Mon Sep 17 00:00:00 2001 From: Mikerah Date: Sat, 26 Mar 2022 22:47:48 -0400 Subject: [PATCH 07/26] Basic handling of variables with types in stoffel lang grammar --- compiler/parser/stoffel_lang.pest | 40 ++++++++++++++++++++++++------- 1 file changed, 31 insertions(+), 9 deletions(-) diff --git a/compiler/parser/stoffel_lang.pest b/compiler/parser/stoffel_lang.pest index 15c599a..1035cc3 100644 --- a/compiler/parser/stoffel_lang.pest +++ b/compiler/parser/stoffel_lang.pest @@ -1,15 +1,37 @@ +WHITESPACE = _{ " " } alpha = {'a'..'z' | 'A'..'Z'} digit = {'0'..'9'} +number = {digit+} ident = { (alpha | digit)+ } -storage_var = {"storage" ~ " " ~ (types | container_types) ~ " " ~ (!digit ~ ident)+ ~ ";"} -types = { "sint" } -container_types = { "Map" ~ "<" ~ (types | ident) ~ "," ~ (types | ident) ~ ">"} -program_def = { "program" ~ " " ~ (!digit ~ ident)+ ~ " " ~ program_block} -program_block = { "{" ~ "}" } +// base types +base_types = { "sint" | "int" | "uint" | "sfix" | "fix" | "sfloat" |"float" | "regint" | "sgf2n" | "gf2n"} -struct_def = { "struct" ~ " " ~ (!digit ~ ident)+ ~ " " ~ struct_block } -struct_block = { "{" ~ "}" } -function_def = { "fn" ~ " " ~ (!digit ~ ident)+ ~ " " ~ function_block } -function_block = { "{" ~ "}" } \ No newline at end of file +// Arrays +array_length = { number+ } +array_dec = { "[" ~ (base_types) ~ ";" ~ (array_length) ~ "]" } + +// Maps +map_keyword = {"Map"} +map_component = {"<" ~ (base_types) ~ "," ~ (base_types | array_dec) ~ ">"} +map_dec = {map_keyword ~ map_component} + + +// Structs +struct_name = @{(!digit ~ ident)+} +struct_keyword = {"struct"} +struct_component_name = @{(!digit ~ ident)+} +struct_component = {struct_component_name ~ ":" ~ (base_types | array_dec) ~ ";"} +struct_block = { "{" ~ " " ~ struct_component+ ~ " " ~ "}"} +struct_dec = {struct_keyword ~ " " ~ struct_name ~ " " ~ struct_block} + +composed_types = {array_dec | map_dec | struct_dec} + +// Variables +variable_name = @{(!digit ~ ident)+} +variable_let_keyword = {"let"} +variable_storage_keyword = {"storage"} +variable_dec = {variable_let_keyword ~ variable_storage_keyword? ~ variable_name ~ ":" ~ (base_types | composed_types) ~ ";"} + +program = _{ SOI ~ EOI} \ No newline at end of file From 989425e5554ddccfa048b347edbb1484eaf2517d Mon Sep 17 00:00:00 2001 From: Mikerah Date: Tue, 17 May 2022 09:02:54 -0400 Subject: [PATCH 08/26] Some syntax changes to hbs1.stf --- examples/stoffel/hbs1.stf | 1 - 1 file changed, 1 deletion(-) diff --git a/examples/stoffel/hbs1.stf b/examples/stoffel/hbs1.stf index 0bd2cad..083f7d2 100644 --- a/examples/stoffel/hbs1.stf +++ b/examples/stoffel/hbs1.stf @@ -23,7 +23,6 @@ program HoneyBadgerSwap { storage sint totalShares; storage Pool pool; - storage Map userData; storage Map lpData; fn constructor(assetAID: sint, amountA: sint, assetBID: sint, amountB: sint) { From b64ae4ea47d3661caf25d90eb1cdcd8185bf9e7c Mon Sep 17 00:00:00 2001 From: Mikerah Date: Sun, 5 Jun 2022 22:49:03 -0400 Subject: [PATCH 09/26] first pest grammar --- compiler/parser/stoffel_lang.pest | 120 +++++++++++++++++++++++++----- 1 file changed, 101 insertions(+), 19 deletions(-) diff --git a/compiler/parser/stoffel_lang.pest b/compiler/parser/stoffel_lang.pest index 1035cc3..8dfbdcf 100644 --- a/compiler/parser/stoffel_lang.pest +++ b/compiler/parser/stoffel_lang.pest @@ -2,36 +2,118 @@ WHITESPACE = _{ " " } alpha = {'a'..'z' | 'A'..'Z'} digit = {'0'..'9'} number = {digit+} -ident = { (alpha | digit)+ } +ident = @{ ASCII_ALPHA ~ (ASCII_ALPHANUMERIC|"_")* } + +// Keywords +for_keyword = {"for"} +while_keyword = {"while"} +if_keyword = {"if"} +else_keyword = {"else"} +struct_keyword = {"struct"} +variable_let_keyword = {"let"} +variable_storage_keyword = {"storage"} +constructor_keyword = {"constructor"} +function_keyword = {"fn"} +fn_returns = {"->"} +path_separator = {"::"} +use_keyword = {"use"} +true_keyword = {"true"} +false_keyword = {"false"} +function_returns = {"->"} +// types +type_sint_keyword = {"sint"} +type_int_keyword = {"int"} +type_uint_keyword = {"uint"} +type_sfix_keyword = {"sfix"} +type_fix_keyword = {"fix"} +type_sfloat_keyword = {"sfloat"} +type_float_keyword = {"float"} +type_regint_keyword = {"regint"} +type_sgf2n_keyword = {"sgf2n"} +type_gf2n_keyword = {"gf2n"} +type_bool_keyword = {"bool"} + +// Comments +line_comment_open = {"//"} +block_comment_open = {"/*"} +block_comment_close = {"*/"} + +arith_ops = {"/" | "*" | "+" | "-" | "**"} +comp_ops = {"==" | ">=" | "<=" | "!=" | ">" | "<"} +logical_ops = {"||" | "&&"} +inc_dec_ops = {"++" | "--"} +unary_ops = {"!"} +ops = {arith_ops | comp_ops | logical_ops | unary_ops} + +code_block = {"{" ~ (declarations | control_flow)* ~ "}"} // base types -base_types = { "sint" | "int" | "uint" | "sfix" | "fix" | "sfloat" |"float" | "regint" | "sgf2n" | "gf2n"} +base_types = { type_fix_keyword | type_float_keyword | + type_gf2n_keyword | type_int_keyword | + type_regint_keyword | type_sfix_keyword | + type_sfloat_keyword | type_sgf2n_keyword | + type_sint_keyword | type_uint_keyword | + type_bool_keyword} + +boolean_values = {true_keyword | false_keyword} + +literal_value = {number | boolean_values} + +expr_inner = { if_exp | code_block | literal_value | struct_component_access | array_index} +expr = {expr_inner ~ (ops ~ expr_inner)*} + +call_item = {ident | "(" ~ expr ~ ")"} // Arrays array_length = { number+ } -array_dec = { "[" ~ (base_types) ~ ";" ~ (array_length) ~ "]" } - -// Maps -map_keyword = {"Map"} -map_component = {"<" ~ (base_types) ~ "," ~ (base_types | array_dec) ~ ">"} -map_dec = {map_keyword ~ map_component} +array_expression = {"[" ~ array_elements ~ "]"} +array_elements = {literal_value ~ ("," ~ array_elements)*} +array_type = {"[" ~ base_types ~ ";" ~ number ~ "]"} +array_index = {call_item ~ "[" ~ expr ~"]" ~ ("[" ~ expr ~ "]")*} // Structs -struct_name = @{(!digit ~ ident)+} -struct_keyword = {"struct"} +struct_name = {ident} struct_component_name = @{(!digit ~ ident)+} -struct_component = {struct_component_name ~ ":" ~ (base_types | array_dec) ~ ";"} -struct_block = { "{" ~ " " ~ struct_component+ ~ " " ~ "}"} -struct_dec = {struct_keyword ~ " " ~ struct_name ~ " " ~ struct_block} +struct_component = {(struct_component_name ~ ":" ~ types ~ ("," ~ struct_component_name ~ ":" ~ types)* ~ ","?)?} +struct_block = { "{" ~ " " ~ struct_component? ~ " " ~ "}"} +struct_dec = {struct_keyword ~ struct_name ~ " " ~ struct_block} +struct_component_access = {subfield_path} +subfield_path = {(sub_subfield_path ~ ".")+ ~ call_item} +sub_subfield_path = {array_index|call_item} -composed_types = {array_dec | map_dec | struct_dec} +composed_types = {array_type| map_dec | struct_dec} + +types = {base_types | composed_types } // Variables -variable_name = @{(!digit ~ ident)+} -variable_let_keyword = {"let"} -variable_storage_keyword = {"storage"} -variable_dec = {variable_let_keyword ~ variable_storage_keyword? ~ variable_name ~ ":" ~ (base_types | composed_types) ~ ";"} +variable_name = {ident} +variable_dec = {variable_let_keyword ~ variable_storage_keyword? ~ variable_name ~ ":" ~ (base_types | composed_types) ~ ( "=" ~ expr)?~ ";"} + +// functions +function_name = {("constructor") | ident} +function_param_name = {ident} +function_args = { ((function_param_name ~ ":" ~ types) ~ ("," ~ (function_param_name ~ ":" ~ types))*)? } +function_signature = { function_keyword ~ function_name ~ "(" ~ function_args? ~ ")" ~ (function_returns ~ types)? } +function_dec = {function_signature ~ code_block} + + +// control flow +condition = {expr ~ (comp_ops | logical_ops) ~ expr} +if_exp = {if_keyword ~ expr ~ code_block ~ (else_keyword ~ (code_block|if_exp))?} +while_loop = {while_keyword ~ expr ~ code_block} +for_loop = {for_keyword ~ "(" ~ variable_dec? ~ ";" ~ condition ~ ";" ~ (expr ~ inc_dec_ops) ~ ")" ~ code_block} +control_flow = {condition | if_exp | while_loop | for_loop} + +// Declarations +non_variable_declarations = {function_dec} +variable_declarations = {variable_dec} +var_reassignment = {variable_name ~ "=" ~ expr ~ ";"} +struct_field_reassignment = {struct_component_access ~ "=" ~ expr ~ ";"} +reassignment = {var_reassignment | struct_field_reassignment} +declarations = {non_variable_declarations | variable_declarations | reassignment} -program = _{ SOI ~ EOI} \ No newline at end of file +program_dec = {"program" ~ ident ~ program_block} +program_block = { "{" ~ expr ~ "}" } +program = _{ SOI ~ program_dec ~ EOI} \ No newline at end of file From 3a5e36a0e9dfe144cb751f105e0dde69a3c37ddc Mon Sep 17 00:00:00 2001 From: Mikerah Date: Sun, 5 Jun 2022 22:56:08 -0400 Subject: [PATCH 10/26] Updated cargo.toml --- compiler/Cargo.toml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/compiler/Cargo.toml b/compiler/Cargo.toml index 41b7a45..8bc9376 100644 --- a/compiler/Cargo.toml +++ b/compiler/Cargo.toml @@ -6,3 +6,5 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +pest = "2.0" +pest_derive = "2.0" \ No newline at end of file From 97c9fbc4ddbd3b16e780d88179ca12e95c795116 Mon Sep 17 00:00:00 2001 From: Mikerah Date: Sun, 5 Jun 2022 23:05:54 -0400 Subject: [PATCH 11/26] Added lib.rs to parser folder in the compiler crate --- compiler/parser/lib.rs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 compiler/parser/lib.rs diff --git a/compiler/parser/lib.rs b/compiler/parser/lib.rs new file mode 100644 index 0000000..d78e257 --- /dev/null +++ b/compiler/parser/lib.rs @@ -0,0 +1,14 @@ +extern crate pest; +#[macro_use] +extern crate pest_derive; + +use std::fs; +use pest::{Parser, iterators::Pairs, error::Error} + +#[derive(Parser)] +#[grammar = "stoffel_lang.pest"] +pub struct StoffelLangParser; + +pub fn parse(input: &str) -> Result, Error> { + unimplemented!(); +} \ No newline at end of file From 5f675afd71aff17d98427913ff13c25e58151010 Mon Sep 17 00:00:00 2001 From: Mikerah Date: Wed, 8 Jun 2022 15:34:22 -0400 Subject: [PATCH 12/26] Fixed whitespace issues --- compiler/parser/stoffel_lang.pest | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/compiler/parser/stoffel_lang.pest b/compiler/parser/stoffel_lang.pest index 8dfbdcf..7466873 100644 --- a/compiler/parser/stoffel_lang.pest +++ b/compiler/parser/stoffel_lang.pest @@ -1,8 +1,10 @@ -WHITESPACE = _{ " " } +WHITESPACE = _{(" "|"\t"|"\r"|"\n")+} alpha = {'a'..'z' | 'A'..'Z'} digit = {'0'..'9'} number = {digit+} ident = @{ ASCII_ALPHA ~ (ASCII_ALPHANUMERIC|"_")* } +block_comment = @{block_comment_open ~ (!block_comment_close ~ ANY)* ~ block_comment_close} +line_comment = @{line_comment_open ~ (!("\r"|"\n") ~ ANY)*} // Keywords for_keyword = {"for"} @@ -59,7 +61,7 @@ boolean_values = {true_keyword | false_keyword} literal_value = {number | boolean_values} -expr_inner = { if_exp | code_block | literal_value | struct_component_access | array_index} +expr_inner = { if_exp | code_block | literal_value | struct_component_access | array_index | struct_dec} expr = {expr_inner ~ (ops ~ expr_inner)*} @@ -77,13 +79,13 @@ array_index = {call_item ~ "[" ~ expr ~"]" ~ ("[" ~ expr ~ "]")*} struct_name = {ident} struct_component_name = @{(!digit ~ ident)+} struct_component = {(struct_component_name ~ ":" ~ types ~ ("," ~ struct_component_name ~ ":" ~ types)* ~ ","?)?} -struct_block = { "{" ~ " " ~ struct_component? ~ " " ~ "}"} -struct_dec = {struct_keyword ~ struct_name ~ " " ~ struct_block} +struct_block = { "{" ~ struct_component? ~ "}"} +struct_dec = {struct_keyword ~ struct_name ~ struct_block} struct_component_access = {subfield_path} subfield_path = {(sub_subfield_path ~ ".")+ ~ call_item} sub_subfield_path = {array_index|call_item} -composed_types = {array_type| map_dec | struct_dec} +composed_types = {array_type| struct_dec} types = {base_types | composed_types } @@ -116,4 +118,4 @@ declarations = {non_variable_declarations | variable_declarations | reassignment program_dec = {"program" ~ ident ~ program_block} program_block = { "{" ~ expr ~ "}" } -program = _{ SOI ~ program_dec ~ EOI} \ No newline at end of file +program = { SOI ~ program_dec ~ EOI} \ No newline at end of file From a0027bd2ef28c4acf20662d54e6dfea127f37011 Mon Sep 17 00:00:00 2001 From: Mikerah Date: Wed, 8 Jun 2022 19:23:39 -0400 Subject: [PATCH 13/26] Fixed program block parsing --- compiler/parser/stoffel_lang.pest | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/parser/stoffel_lang.pest b/compiler/parser/stoffel_lang.pest index 7466873..785cba7 100644 --- a/compiler/parser/stoffel_lang.pest +++ b/compiler/parser/stoffel_lang.pest @@ -109,7 +109,7 @@ for_loop = {for_keyword ~ "(" ~ variable_dec? ~ ";" ~ condition ~ ";" ~ (expr ~ control_flow = {condition | if_exp | while_loop | for_loop} // Declarations -non_variable_declarations = {function_dec} +non_variable_declarations = {function_dec | struct_dec} variable_declarations = {variable_dec} var_reassignment = {variable_name ~ "=" ~ expr ~ ";"} struct_field_reassignment = {struct_component_access ~ "=" ~ expr ~ ";"} @@ -117,5 +117,5 @@ reassignment = {var_reassignment | struct_field_reassignment} declarations = {non_variable_declarations | variable_declarations | reassignment} program_dec = {"program" ~ ident ~ program_block} -program_block = { "{" ~ expr ~ "}" } +program_block = { "{" ~ non_variable_declarations* ~ "}" } program = { SOI ~ program_dec ~ EOI} \ No newline at end of file From 7c36df106907aa9c2f101271261ac91191c587e4 Mon Sep 17 00:00:00 2001 From: Mikerah Date: Wed, 8 Jun 2022 21:44:09 -0400 Subject: [PATCH 14/26] Added storage and amended types to include struct types --- compiler/parser/stoffel_lang.pest | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/compiler/parser/stoffel_lang.pest b/compiler/parser/stoffel_lang.pest index 785cba7..470da13 100644 --- a/compiler/parser/stoffel_lang.pest +++ b/compiler/parser/stoffel_lang.pest @@ -71,7 +71,7 @@ call_item = {ident | "(" ~ expr ~ ")"} array_length = { number+ } array_expression = {"[" ~ array_elements ~ "]"} array_elements = {literal_value ~ ("," ~ array_elements)*} -array_type = {"[" ~ base_types ~ ";" ~ number ~ "]"} +array_type = {"[" ~ types ~ ";" ~ array_length ~ "]"} array_index = {call_item ~ "[" ~ expr ~"]" ~ ("[" ~ expr ~ "]")*} @@ -85,7 +85,7 @@ struct_component_access = {subfield_path} subfield_path = {(sub_subfield_path ~ ".")+ ~ call_item} sub_subfield_path = {array_index|call_item} -composed_types = {array_type| struct_dec} +composed_types = {array_type| struct_name} types = {base_types | composed_types } @@ -93,6 +93,11 @@ types = {base_types | composed_types } variable_name = {ident} variable_dec = {variable_let_keyword ~ variable_storage_keyword? ~ variable_name ~ ":" ~ (base_types | composed_types) ~ ( "=" ~ expr)?~ ";"} +// Storage +storage_dec = {variable_storage_keyword ~ "{" ~ storage_fields ~ "}"} +storage_fields = {storage_field ~ ("," ~ storage_field)* ~ ","?} +storage_field = {ident ~ ":" ~ types} + // functions function_name = {("constructor") | ident} function_param_name = {ident} @@ -109,7 +114,7 @@ for_loop = {for_keyword ~ "(" ~ variable_dec? ~ ";" ~ condition ~ ";" ~ (expr ~ control_flow = {condition | if_exp | while_loop | for_loop} // Declarations -non_variable_declarations = {function_dec | struct_dec} +non_variable_declarations = {function_dec | struct_dec | storage_dec} variable_declarations = {variable_dec} var_reassignment = {variable_name ~ "=" ~ expr ~ ";"} struct_field_reassignment = {struct_component_access ~ "=" ~ expr ~ ";"} From f0339523591adc45d3694555798349e5f8f0967b Mon Sep 17 00:00:00 2001 From: Mikerah Date: Wed, 8 Jun 2022 21:57:14 -0400 Subject: [PATCH 15/26] removed constructor keyword. Will take into account after the parsing as opposed to within the grammar --- compiler/parser/stoffel_lang.pest | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/parser/stoffel_lang.pest b/compiler/parser/stoffel_lang.pest index 470da13..003c819 100644 --- a/compiler/parser/stoffel_lang.pest +++ b/compiler/parser/stoffel_lang.pest @@ -99,7 +99,7 @@ storage_fields = {storage_field ~ ("," ~ storage_field)* ~ ","?} storage_field = {ident ~ ":" ~ types} // functions -function_name = {("constructor") | ident} +function_name = {ident} function_param_name = {ident} function_args = { ((function_param_name ~ ":" ~ types) ~ ("," ~ (function_param_name ~ ":" ~ types))*)? } function_signature = { function_keyword ~ function_name ~ "(" ~ function_args? ~ ")" ~ (function_returns ~ types)? } From 17a97f756b10751a643d3cce1f53b01163e6ead2 Mon Sep 17 00:00:00 2001 From: Mikerah Date: Wed, 8 Jun 2022 22:02:29 -0400 Subject: [PATCH 16/26] cleaned up variables related grammar and fixed grammar for operations with variables --- compiler/parser/stoffel_lang.pest | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/parser/stoffel_lang.pest b/compiler/parser/stoffel_lang.pest index 003c819..787a19c 100644 --- a/compiler/parser/stoffel_lang.pest +++ b/compiler/parser/stoffel_lang.pest @@ -61,7 +61,7 @@ boolean_values = {true_keyword | false_keyword} literal_value = {number | boolean_values} -expr_inner = { if_exp | code_block | literal_value | struct_component_access | array_index | struct_dec} +expr_inner = { if_exp | code_block | literal_value | struct_component_access | array_index | struct_dec | variable_name} expr = {expr_inner ~ (ops ~ expr_inner)*} @@ -91,7 +91,7 @@ types = {base_types | composed_types } // Variables variable_name = {ident} -variable_dec = {variable_let_keyword ~ variable_storage_keyword? ~ variable_name ~ ":" ~ (base_types | composed_types) ~ ( "=" ~ expr)?~ ";"} +variable_dec = {variable_let_keyword ~ variable_name ~ ":" ~ types ~ ( "=" ~ expr)?~ ";"} // Storage storage_dec = {variable_storage_keyword ~ "{" ~ storage_fields ~ "}"} From 5d29a3a1729434a76a4fcd1b10963fce44ab7c61 Mon Sep 17 00:00:00 2001 From: Mikerah Date: Thu, 9 Jun 2022 11:59:44 -0400 Subject: [PATCH 17/26] Fixed struct usage --- compiler/parser/stoffel_lang.pest | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/compiler/parser/stoffel_lang.pest b/compiler/parser/stoffel_lang.pest index 787a19c..097a161 100644 --- a/compiler/parser/stoffel_lang.pest +++ b/compiler/parser/stoffel_lang.pest @@ -61,12 +61,17 @@ boolean_values = {true_keyword | false_keyword} literal_value = {number | boolean_values} -expr_inner = { if_exp | code_block | literal_value | struct_component_access | array_index | struct_dec | variable_name} +expr_inner = { if_exp | code_block | literal_value | struct_component_access | array_index | struct_expression | variable_name} expr = {expr_inner ~ (ops ~ expr_inner)*} call_item = {ident | "(" ~ expr ~ ")"} +// call path +call_path = {relative_call_path|absolute_call_path} +relative_call_path = {ident ~ (path_separator ~ ident)*} +absolute_call_path = {path_separator ~ ident ~ (path_separator ~ ident)*} + // Arrays array_length = { number+ } array_expression = {"[" ~ array_elements ~ "]"} @@ -84,6 +89,8 @@ struct_dec = {struct_keyword ~ struct_name ~ struct_block} struct_component_access = {subfield_path} subfield_path = {(sub_subfield_path ~ ".")+ ~ call_item} sub_subfield_path = {array_index|call_item} +struct_expression = {call_path ~ "{" ~ struct_expr_component ~ "}"} +struct_expr_component = {(struct_component_name ~ ":" ~ expr ~ ("," ~ struct_component_name ~ ":" ~ expr)* ~ ","?)?} composed_types = {array_type| struct_name} @@ -118,7 +125,8 @@ non_variable_declarations = {function_dec | struct_dec | storage_dec} variable_declarations = {variable_dec} var_reassignment = {variable_name ~ "=" ~ expr ~ ";"} struct_field_reassignment = {struct_component_access ~ "=" ~ expr ~ ";"} -reassignment = {var_reassignment | struct_field_reassignment} +storage_reassignment = {variable_storage_keyword ~ "." ~ ident ~ ("." ~ ident)* ~ "=" ~ expr ~ ";"} +reassignment = {var_reassignment | struct_field_reassignment | storage_reassignment} declarations = {non_variable_declarations | variable_declarations | reassignment} program_dec = {"program" ~ ident ~ program_block} From add531cbf5d4a1318bdbd9b93a8e7715757f82b2 Mon Sep 17 00:00:00 2001 From: Mikerah Date: Thu, 9 Jun 2022 16:54:33 -0400 Subject: [PATCH 18/26] Fixed for loop rule in grammar --- compiler/parser/stoffel_lang.pest | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/compiler/parser/stoffel_lang.pest b/compiler/parser/stoffel_lang.pest index 097a161..f5c5dbc 100644 --- a/compiler/parser/stoffel_lang.pest +++ b/compiler/parser/stoffel_lang.pest @@ -1,7 +1,7 @@ WHITESPACE = _{(" "|"\t"|"\r"|"\n")+} alpha = {'a'..'z' | 'A'..'Z'} digit = {'0'..'9'} -number = {digit+} +number = {ASCII_DIGIT+} ident = @{ ASCII_ALPHA ~ (ASCII_ALPHANUMERIC|"_")* } block_comment = @{block_comment_open ~ (!block_comment_close ~ ANY)* ~ block_comment_close} line_comment = @{line_comment_open ~ (!("\r"|"\n") ~ ANY)*} @@ -43,7 +43,6 @@ block_comment_close = {"*/"} arith_ops = {"/" | "*" | "+" | "-" | "**"} comp_ops = {"==" | ">=" | "<=" | "!=" | ">" | "<"} logical_ops = {"||" | "&&"} -inc_dec_ops = {"++" | "--"} unary_ops = {"!"} ops = {arith_ops | comp_ops | logical_ops | unary_ops} @@ -61,9 +60,10 @@ boolean_values = {true_keyword | false_keyword} literal_value = {number | boolean_values} -expr_inner = { if_exp | code_block | literal_value | struct_component_access | array_index | struct_expression | variable_name} +expr_inner = { if_exp | code_block | literal_value | struct_component_access | array_index | struct_expression | variable_name | unary_op_expr} expr = {expr_inner ~ (ops ~ expr_inner)*} +unary_op_expr = { unary_ops ~ expr_inner } call_item = {ident | "(" ~ expr ~ ")"} @@ -114,16 +114,15 @@ function_dec = {function_signature ~ code_block} // control flow -condition = {expr ~ (comp_ops | logical_ops) ~ expr} if_exp = {if_keyword ~ expr ~ code_block ~ (else_keyword ~ (code_block|if_exp))?} while_loop = {while_keyword ~ expr ~ code_block} -for_loop = {for_keyword ~ "(" ~ variable_dec? ~ ";" ~ condition ~ ";" ~ (expr ~ inc_dec_ops) ~ ")" ~ code_block} -control_flow = {condition | if_exp | while_loop | for_loop} +for_loop = {for_keyword ~ "(" ~ (variable_dec | var_reassignment)? ~ ";"? ~ expr ~ ";" ~ var_reassignment ~ ")" ~ code_block} +control_flow = {if_exp | while_loop | for_loop} // Declarations non_variable_declarations = {function_dec | struct_dec | storage_dec} variable_declarations = {variable_dec} -var_reassignment = {variable_name ~ "=" ~ expr ~ ";"} +var_reassignment = {variable_name ~ "=" ~ expr ~ ";"?} struct_field_reassignment = {struct_component_access ~ "=" ~ expr ~ ";"} storage_reassignment = {variable_storage_keyword ~ "." ~ ident ~ ("." ~ ident)* ~ "=" ~ expr ~ ";"} reassignment = {var_reassignment | struct_field_reassignment | storage_reassignment} From ee976043244cae7a8a74fc4c377a6c6a329393c1 Mon Sep 17 00:00:00 2001 From: Mikerah Date: Thu, 9 Jun 2022 18:17:24 -0400 Subject: [PATCH 19/26] added shorthand operators to grammar --- compiler/parser/stoffel_lang.pest | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/compiler/parser/stoffel_lang.pest b/compiler/parser/stoffel_lang.pest index f5c5dbc..26bf680 100644 --- a/compiler/parser/stoffel_lang.pest +++ b/compiler/parser/stoffel_lang.pest @@ -42,6 +42,7 @@ block_comment_close = {"*/"} arith_ops = {"/" | "*" | "+" | "-" | "**"} comp_ops = {"==" | ">=" | "<=" | "!=" | ">" | "<"} +arith_assign_ops = { "+=" | "-=" | "/=" | "*=" } logical_ops = {"||" | "&&"} unary_ops = {"!"} ops = {arith_ops | comp_ops | logical_ops | unary_ops} @@ -114,17 +115,18 @@ function_dec = {function_signature ~ code_block} // control flow +condition = {expr ~ (comp_ops | logical_ops) ~ expr} if_exp = {if_keyword ~ expr ~ code_block ~ (else_keyword ~ (code_block|if_exp))?} while_loop = {while_keyword ~ expr ~ code_block} for_loop = {for_keyword ~ "(" ~ (variable_dec | var_reassignment)? ~ ";"? ~ expr ~ ";" ~ var_reassignment ~ ")" ~ code_block} -control_flow = {if_exp | while_loop | for_loop} +control_flow = {condition | if_exp | while_loop | for_loop} // Declarations non_variable_declarations = {function_dec | struct_dec | storage_dec} variable_declarations = {variable_dec} -var_reassignment = {variable_name ~ "=" ~ expr ~ ";"?} -struct_field_reassignment = {struct_component_access ~ "=" ~ expr ~ ";"} -storage_reassignment = {variable_storage_keyword ~ "." ~ ident ~ ("." ~ ident)* ~ "=" ~ expr ~ ";"} +var_reassignment = {variable_name ~ ("=" | arith_assign_ops) ~ expr ~ ";"?} +struct_field_reassignment = {struct_component_access ~ ("=" | arith_assign_ops) ~ expr ~ ";"} +storage_reassignment = {variable_storage_keyword ~ "." ~ ident ~ ("." ~ ident)* ~ ("=" | arith_assign_ops) ~ expr ~ ";"} reassignment = {var_reassignment | struct_field_reassignment | storage_reassignment} declarations = {non_variable_declarations | variable_declarations | reassignment} From a0d7499ebad09219576cc7e4ee1ba002c5756295 Mon Sep 17 00:00:00 2001 From: Mikerah Date: Thu, 9 Jun 2022 19:34:52 -0400 Subject: [PATCH 20/26] fixed issues with expression within parentheses in the grammar --- compiler/parser/stoffel_lang.pest | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/compiler/parser/stoffel_lang.pest b/compiler/parser/stoffel_lang.pest index 26bf680..1911cbe 100644 --- a/compiler/parser/stoffel_lang.pest +++ b/compiler/parser/stoffel_lang.pest @@ -48,6 +48,7 @@ unary_ops = {"!"} ops = {arith_ops | comp_ops | logical_ops | unary_ops} code_block = {"{" ~ (declarations | control_flow)* ~ "}"} +parenthesized_expr = {"(" ~ expr ~ ")"} // base types base_types = { type_fix_keyword | type_float_keyword | @@ -61,7 +62,7 @@ boolean_values = {true_keyword | false_keyword} literal_value = {number | boolean_values} -expr_inner = { if_exp | code_block | literal_value | struct_component_access | array_index | struct_expression | variable_name | unary_op_expr} +expr_inner = { if_exp | code_block | literal_value | struct_component_access | array_index | struct_expression | variable_name | unary_op_expr | parenthesized_expr} expr = {expr_inner ~ (ops ~ expr_inner)*} unary_op_expr = { unary_ops ~ expr_inner } From c392d0255ab157c5a5d26f0a62309358dcc281bc Mon Sep 17 00:00:00 2001 From: Mikerah Date: Thu, 9 Jun 2022 19:37:10 -0400 Subject: [PATCH 21/26] Modified HoneyBadgerSwap example to fit newer grammar --- examples/stoffel/hbs.stf | 88 +++++++++++++++++++++++++++++++++++++++ examples/stoffel/hbs1.stf | 83 ------------------------------------ examples/stoffel/hbs2.stf | 81 ----------------------------------- 3 files changed, 88 insertions(+), 164 deletions(-) create mode 100644 examples/stoffel/hbs.stf delete mode 100644 examples/stoffel/hbs1.stf delete mode 100644 examples/stoffel/hbs2.stf diff --git a/examples/stoffel/hbs.stf b/examples/stoffel/hbs.stf new file mode 100644 index 0000000..38a457e --- /dev/null +++ b/examples/stoffel/hbs.stf @@ -0,0 +1,88 @@ +program HoneyBadgerSwap { + struct Pool { + amountA: sfloat, + amountB: sfloat, + } + + struct UserData { + userID: sint, + balanceA: sfloat, + balanceB: sfloat, + shares: sint + } + + storage { + traders: [UserData; 3], + liquidity_providers: [UserData; 3], + pool: Pool, + total_shares: sint + } + + fn addLiquidity(max_amountA: sfloat, amountB: sfloat, lpID: sint) { + let total_liquidity: sint = storage.total_shares; + if total_liquidity > 0 { + let tokenB_reserve: sfloat = storage.balanceB - amountB; + let tokenA_reserve: sfloat = storage.balanceA; + let new_amountA: sfloat = amountB * tokenA_reserve / tokenB_reserve + 1; + let liquidity_minted: sint = amountB * total_liquidity / tokenB_reserve; + storage.liquidity_providers[lpID].shares += liquidity_minted; + storage.total_shares += liquidity_minted; + storage.pool.amountB += amountB; + storage.pool.amountA += new_amountA; + storage.liquidity_providers[lpID].amountB -= amountB; + storage.liquidity_providers[lpID].amountA -= new_amountA; + } + else { + let new_amountA: sfloat = max_amountA; + let initial_liquidity: sint = amountB; + storage.total_shares = initial_liquidity; + storage.liquidity_providers[lpID].shares = initial_liquidity; + storage.liquidity_providers[lpID].amountA -= max_amountA; + storage.liquidity_providers[lpID].amountB -= amountB; + storage.pool.amountA += new_amountA; + storage.pool.amountB += amountB; + } + + } + + fn removeLiquidity(shares: sint, min_amountA: sfloat, min_amountB: sfloat, lpID: sint) { + let total_liquidity: sint = storage.total_shares; + let tokenB_reserve: sfloat = storage.pool.amountB; + let tokenA_amount: sfloat = shares * storage.pool.amountA / total_liquidity; + let tokenB_amount: sfloat = shares * tokenB_reserve / total_liquidity; + storage.liquidity_providers[lpID].shares -= shares; + storage.total_shares -= shares; + storage.liquidity_providers[lpID].amountA += tokenA_amount; + storage.liquidity_providers[lpID].amountB += tokenB_amount; + } + + fn deposit(amountA: sfloat, amountB: sfloat, userID: sint, is_lp: bool) { + if is_lp == true { + storage.liquidity_providers[userID].amountA += amountA; + storage.liquidity_providers[userID].amountB += amountB; + } else { + storage.traders[userID].amountA += amountA; + storage.traders[userID].amountB += amountB; + } + } + + fn withdraw(amountA: sfloat, amountB: sfloat, userID: sint, is_lp: bool) { + if is_lp == true { + storage.liquidity_providers[userID].amountA -= amountA; + storage.liquidity_providers[userID].amountB -= amountB; + } else { + storage.traders[userID].amountA -= amountA; + storage.traders[userID].amountB -= amountB; + } + } + + fn trade(tokenA_sold: sfloat, min_tokenB: sfloat, traderID: sint) { + let tokenB_reserve: sfloat = storage.pool.amountB; + let tokenA_sold_with_fee: sfloat = tokenA_sold * 997; + let numerator: sfloat = tokenA_sold_with_fee * tokenB_reserve; + let denominator: sfloat = (storage.pool.amountA * 1000) + tokenA_sold_with_fee; + let tokenB_bought: sfloat = numerator / denominator; + storage.traders[traderID].amountA -= tokenA_sold; + storage.traders[traderID].amountB += tokenB_bought; + } +} \ No newline at end of file diff --git a/examples/stoffel/hbs1.stf b/examples/stoffel/hbs1.stf deleted file mode 100644 index 083f7d2..0000000 --- a/examples/stoffel/hbs1.stf +++ /dev/null @@ -1,83 +0,0 @@ -// HBS where we care about the privacy of traders and LPs - -program HoneyBadgerSwap { - struct Pool { - assetAID: int, - assetBID: int, - amountA: sint, - amountB: sint, - k: sint - } - - struct UserData { - userID: sint, - assets: Map - } - - struct LPData { - lpID: sint, - shares: sint, - userData: UserData - } - - storage sint totalShares; - storage Pool pool; - - storage Map lpData; - - fn constructor(assetAID: sint, amountA: sint, assetBID: sint, amountB: sint) { - sint k = amountA * amountB; - pool = Pool {assetAID: assetAID, amountA: amountA, assetBID:assetBID, amountB: amountB, k: k}; - } - - // Will need to create an unsigned integer type for the language - pub fn Trade(amountA: sint, amountB: sint) -> bool { - // But since we don't have an unsigned type (yet), we need to do a check which is expensive - if amountA < 0 or amount B < 0 { - return false; - } - - sint newAmountA = pools[0].amountA - amountA; - sint priceAssetB = pools[0].k / (pools[0].amountA - newAmountA) - sint newAmountB = pools[0].k / priceAssetB - - userData[userID].assets[assetA] -= amountA; - userData[userID].assets[assetB] += amountB; - - pools[0].amountA = newAmountA; - pools[0].amountB = newAmountB; - } - - // Obviously, needs way more input validation. Will be added when we have more details - // about the language for a complete, realistic example. - pub fn AddLiquidity(lpID: sint, amountA: sint, maxAmountB: sint) -> sint { - sint tokenBAmount = (amountA * pool.amountB) / pool.amountA; - sint sharesMinted = (amountA * totalShares) / pool.amountA; - - lpData[lpID].shares += sharesMinted; - totalShares += sharesMinted; - - lpData[lpID].userData.amountA += amountA; - lpData[lpID].userData.amountB += amountB; - - pool.amountA += amountA; - pool.amountB += tokenBAmount; - - } - - // Again, missing some basic functionality but does what we need to do for basic ideation on syntax - pub fn RemoveLiquidity(lpID: sint, shares: sint) { - sint amountA = (shares * pool.amountA) / totalShares; - sint amountB = (shares * pool.amountB) / totalShares; - - lpData[lpID].shares -= shares; - totalShares -= shares; - - lpData[lpID].userData.amountA -= amountA; - lpData[lpID].userData.amountB -= amountB; - - pool.amountA -= amountA; - pool.amountB -= amountB; - } - -} \ No newline at end of file diff --git a/examples/stoffel/hbs2.stf b/examples/stoffel/hbs2.stf deleted file mode 100644 index 0bc26db..0000000 --- a/examples/stoffel/hbs2.stf +++ /dev/null @@ -1,81 +0,0 @@ -// HBS where we only care about trader amounts - -program HoneyBadgerSwap { - struct Pool { - assetAID: int, - assetBID: int, - amountA: sint, - amountB: sint - } - - struct UserData { - userID: int, - assets: Map - } - - struct LPData { - lpID: sint, - shares: sint, - userData: UserData - } - - storage Pool pool; - - storage Map userData; - storage Map lpData; - - fn constructor(assetAID: sint, amountA: sint, assetBID: sint, amountB: sint) { - sint k = amountA * amountB; - pool = Pool {assetAID: assetAID, amountA: amountA, assetBID:assetBID, amountB: amountB, k: k}; - } - - // Will need to create an unsigned integer type for the language - pub fn Trade(userID: int, amountA: sint, amountB: sint) -> bool { - if amountA < 0 or amount B < 0 { - return false; - } - - sint newAmountA = pools[0].amountA - amountA; - sint priceAssetB = pools[0].k / (pools[0].amountA - newAmountA) - sint newAmountB = pools[0].k / priceAssetB - - userData[userID].assets[assetA] -= amountA; - userData[userID].assets[assetB] += amountB; - - pools[0].amountA = newAmountA; - pools[0].amountB = newAmountB; - } - - - // Obviously, needs way more input validation. Will be added when we have more details - // about the language for a complete, realistic example. - pub fn AddLiquidity(lpID: int, amountA: sint, maxAmountB: sint) -> sint { - sint tokenBAmount = (amountA * pool.amountB) / pool.amountA; - sint sharesMinted = (amountA * totalShares) / pool.amountA; - - lpData[lpID].shares += sharesMinted; - totalShares += sharesMinted; - - lpData[lpID].userData.amountA += amountA; - lpData[lpID].userData.amountB += amountB; - - pool.amountA += amountA; - pool.amountB += tokenBAmount; - - } - - // Again, missing some basic functionality but does what we need to do for basic ideation on syntax - pub fn RemoveLiquidity(lpID: int, shares: sint) { - sint amountA = (shares * pool.amountA) / totalShares; - sint amountB = (shares * pool.amountB) / totalShares; - - lpData[lpID].shares -= shares; - totalShares -= shares; - - lpData[lpID].userData.amountA -= amountA; - lpData[lpID].userData.amountB -= amountB; - - pool.amountA -= amountA; - pool.amountB -= amountB; - } -} \ No newline at end of file From 07ddcecefdb4e65535bd4bf767648fc36bf5cdaa Mon Sep 17 00:00:00 2001 From: Mikerah Date: Sat, 11 Jun 2022 12:37:14 -0400 Subject: [PATCH 22/26] Added mpc keyword to denote functions that are meant to be executed by MPC nodes. --- compiler/parser/stoffel_lang.pest | 3 ++- examples/stoffel/hbs.stf | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/compiler/parser/stoffel_lang.pest b/compiler/parser/stoffel_lang.pest index 1911cbe..b32f653 100644 --- a/compiler/parser/stoffel_lang.pest +++ b/compiler/parser/stoffel_lang.pest @@ -22,6 +22,7 @@ use_keyword = {"use"} true_keyword = {"true"} false_keyword = {"false"} function_returns = {"->"} +mpc_keyword = {"mpc"} // types type_sint_keyword = {"sint"} type_int_keyword = {"int"} @@ -111,7 +112,7 @@ storage_field = {ident ~ ":" ~ types} function_name = {ident} function_param_name = {ident} function_args = { ((function_param_name ~ ":" ~ types) ~ ("," ~ (function_param_name ~ ":" ~ types))*)? } -function_signature = { function_keyword ~ function_name ~ "(" ~ function_args? ~ ")" ~ (function_returns ~ types)? } +function_signature = { function_keyword ~ mpc_keyword? ~ function_name ~ "(" ~ function_args? ~ ")" ~ (function_returns ~ types)? } function_dec = {function_signature ~ code_block} diff --git a/examples/stoffel/hbs.stf b/examples/stoffel/hbs.stf index 38a457e..e7b3a86 100644 --- a/examples/stoffel/hbs.stf +++ b/examples/stoffel/hbs.stf @@ -76,7 +76,7 @@ program HoneyBadgerSwap { } } - fn trade(tokenA_sold: sfloat, min_tokenB: sfloat, traderID: sint) { + fn mpc trade(tokenA_sold: sfloat, min_tokenB: sfloat, traderID: sint) { let tokenB_reserve: sfloat = storage.pool.amountB; let tokenA_sold_with_fee: sfloat = tokenA_sold * 997; let numerator: sfloat = tokenA_sold_with_fee * tokenB_reserve; From d459be8f00788f46396dd8ab1ab81936fe8d48a4 Mon Sep 17 00:00:00 2001 From: Mikerah Date: Sat, 11 Jun 2022 16:48:18 -0400 Subject: [PATCH 23/26] Added placeholder errors for parser --- compiler/parser/errors/lib.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 compiler/parser/errors/lib.rs diff --git a/compiler/parser/errors/lib.rs b/compiler/parser/errors/lib.rs new file mode 100644 index 0000000..3704309 --- /dev/null +++ b/compiler/parser/errors/lib.rs @@ -0,0 +1,10 @@ + +#[derive(Debug, Error)] +pub enum ProgramParserError { + +} + +#[derive(Debug, Error)] +pub enum SyntaxError { + +} \ No newline at end of file From 151bf0800e083d47ee75ac54baa9cae0fc441fe0 Mon Sep 17 00:00:00 2001 From: Mikerah Date: Sat, 11 Jun 2022 18:10:14 -0400 Subject: [PATCH 24/26] Modified compiler crate to be a lib instead of an executable --- compiler/Cargo.toml | 4 +- compiler/parser/lib.rs | 14 ----- compiler/src/lib.rs | 1 + compiler/src/main.rs | 3 - .../lib.rs => src/parser/errors/mod.rs} | 0 compiler/src/parser/mod.rs | 58 +++++++++++++++++++ compiler/{ => src}/parser/stoffel_lang.pest | 0 7 files changed, 62 insertions(+), 18 deletions(-) delete mode 100644 compiler/parser/lib.rs create mode 100644 compiler/src/lib.rs delete mode 100644 compiler/src/main.rs rename compiler/{parser/errors/lib.rs => src/parser/errors/mod.rs} (100%) create mode 100644 compiler/src/parser/mod.rs rename compiler/{ => src}/parser/stoffel_lang.pest (100%) diff --git a/compiler/Cargo.toml b/compiler/Cargo.toml index 8bc9376..edf4116 100644 --- a/compiler/Cargo.toml +++ b/compiler/Cargo.toml @@ -7,4 +7,6 @@ edition = "2021" [dependencies] pest = "2.0" -pest_derive = "2.0" \ No newline at end of file +pest_derive = "2.0" +from-pest = "0.3.1" +pest-ast = "0.3.3" \ No newline at end of file diff --git a/compiler/parser/lib.rs b/compiler/parser/lib.rs deleted file mode 100644 index d78e257..0000000 --- a/compiler/parser/lib.rs +++ /dev/null @@ -1,14 +0,0 @@ -extern crate pest; -#[macro_use] -extern crate pest_derive; - -use std::fs; -use pest::{Parser, iterators::Pairs, error::Error} - -#[derive(Parser)] -#[grammar = "stoffel_lang.pest"] -pub struct StoffelLangParser; - -pub fn parse(input: &str) -> Result, Error> { - unimplemented!(); -} \ No newline at end of file diff --git a/compiler/src/lib.rs b/compiler/src/lib.rs new file mode 100644 index 0000000..b2819a7 --- /dev/null +++ b/compiler/src/lib.rs @@ -0,0 +1 @@ +pub mod parser; \ No newline at end of file diff --git a/compiler/src/main.rs b/compiler/src/main.rs deleted file mode 100644 index e7a11a9..0000000 --- a/compiler/src/main.rs +++ /dev/null @@ -1,3 +0,0 @@ -fn main() { - println!("Hello, world!"); -} diff --git a/compiler/parser/errors/lib.rs b/compiler/src/parser/errors/mod.rs similarity index 100% rename from compiler/parser/errors/lib.rs rename to compiler/src/parser/errors/mod.rs diff --git a/compiler/src/parser/mod.rs b/compiler/src/parser/mod.rs new file mode 100644 index 0000000..ed84edd --- /dev/null +++ b/compiler/src/parser/mod.rs @@ -0,0 +1,58 @@ +extern crate pest; +#[macro_use] +extern crate pest_derive; + +use std::{fs, path::Path}; +use pest::{Parser, iterators::Pairs, error::Error, Span}; +use from_pest::FromPest; +use pest_ast::FromPest; + +pub mod errors; +pub use errors::*; + +#[derive(Parser)] +#[grammar = "stoffel_lang.pest"] +pub struct StoffelLangParser; + +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::program))] +pub struct Program {}; + +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::program_dec))] +pub struct ProgramDec {}; + +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::EOI)] +pub struct EOI; + +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::ident)] +pub struct Ident; + +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::expr] +pub struct Expr {}; + +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::expr_inner] +pub struct ExprInner {}; + +pub fn parse(input: &str) -> Result, Error> { + StoffelLangParser::parse(Rule::program, input); +} + +pub fn span_into_string(span: Span) -> String { + span.as_str().to_string(); +} + +impl StoffelLangParser { + /// Reads file into string. + pub fn load_file(file_path: &Path) -> Result { + todo!(); + } + + pub fn parse_file(input_file: &str) -> Result { + todo!(); + } +} \ No newline at end of file diff --git a/compiler/parser/stoffel_lang.pest b/compiler/src/parser/stoffel_lang.pest similarity index 100% rename from compiler/parser/stoffel_lang.pest rename to compiler/src/parser/stoffel_lang.pest From 5dbce83ace710ec4af8d9e42d38d2e072105c4c4 Mon Sep 17 00:00:00 2001 From: Mikerah Date: Sat, 11 Jun 2022 19:21:35 -0400 Subject: [PATCH 25/26] Reorganized compiler crate and added parser skeleton --- compiler/Cargo.toml | 3 +- compiler/src/lib.rs | 3 + compiler/src/parser/errors/mod.rs | 1 + compiler/src/parser/mod.rs | 74 +++++++++++++++++---- compiler/src/{parser => }/stoffel_lang.pest | 0 5 files changed, 66 insertions(+), 15 deletions(-) rename compiler/src/{parser => }/stoffel_lang.pest (100%) diff --git a/compiler/Cargo.toml b/compiler/Cargo.toml index edf4116..ef3fc09 100644 --- a/compiler/Cargo.toml +++ b/compiler/Cargo.toml @@ -9,4 +9,5 @@ edition = "2021" pest = "2.0" pest_derive = "2.0" from-pest = "0.3.1" -pest-ast = "0.3.3" \ No newline at end of file +pest-ast = "0.3.3" +thiserror = "1.0" \ No newline at end of file diff --git a/compiler/src/lib.rs b/compiler/src/lib.rs index b2819a7..6e20f29 100644 --- a/compiler/src/lib.rs +++ b/compiler/src/lib.rs @@ -1 +1,4 @@ +#[macro_use] +extern crate pest_derive; + pub mod parser; \ No newline at end of file diff --git a/compiler/src/parser/errors/mod.rs b/compiler/src/parser/errors/mod.rs index 3704309..3e8101b 100644 --- a/compiler/src/parser/errors/mod.rs +++ b/compiler/src/parser/errors/mod.rs @@ -1,3 +1,4 @@ +use thiserror::Error; #[derive(Debug, Error)] pub enum ProgramParserError { diff --git a/compiler/src/parser/mod.rs b/compiler/src/parser/mod.rs index ed84edd..8fc5536 100644 --- a/compiler/src/parser/mod.rs +++ b/compiler/src/parser/mod.rs @@ -1,6 +1,4 @@ extern crate pest; -#[macro_use] -extern crate pest_derive; use std::{fs, path::Path}; use pest::{Parser, iterators::Pairs, error::Error, Span}; @@ -16,34 +14,82 @@ pub struct StoffelLangParser; #[derive(Clone, Debug, FromPest, PartialEq)] #[pest_ast(rule(Rule::program))] -pub struct Program {}; +pub struct Program {} #[derive(Clone, Debug, FromPest, PartialEq)] #[pest_ast(rule(Rule::program_dec))] -pub struct ProgramDec {}; +pub struct ProgramDec {} #[derive(Clone, Debug, FromPest, PartialEq)] -#[pest_ast(rule(Rule::EOI)] -pub struct EOI; +#[pest_ast(rule(Rule::program_block))] +pub struct ProgramBlock {} #[derive(Clone, Debug, FromPest, PartialEq)] -#[pest_ast(rule(Rule::ident)] -pub struct Ident; +#[pest_ast(rule(Rule::non_variable_declarations))] +pub struct NonVarDecs {} #[derive(Clone, Debug, FromPest, PartialEq)] -#[pest_ast(rule(Rule::expr] -pub struct Expr {}; +#[pest_ast(rule(Rule::EOI))] +pub struct EOI {} #[derive(Clone, Debug, FromPest, PartialEq)] -#[pest_ast(rule(Rule::expr_inner] -pub struct ExprInner {}; +#[pest_ast(rule(Rule::ident))] +pub struct Ident {} + +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::expr))] +pub struct Expr {} + +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::expr_inner))] +pub struct ExprInner {} + +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::if_exp))] +pub struct IfExpr {} + +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::code_block))] +pub struct CodeBlock {} + +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::literal_value))] +pub struct LiteralValue {} + +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::parenthesized_expr))] +pub struct ParenthesizedExpr {} + +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::struct_dec))] +pub struct StructDec {} + +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::variable_dec))] +pub struct VariableDec {} + +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::storage_dec))] +pub struct StorageDec {} + +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::function_dec))] +pub struct FunctionDec {} + +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::while_loop))] +pub struct WhileLoop {} + +#[derive(Clone, Debug, FromPest, PartialEq)] +#[pest_ast(rule(Rule::for_loop))] +pub struct ForLoop {} pub fn parse(input: &str) -> Result, Error> { - StoffelLangParser::parse(Rule::program, input); + StoffelLangParser::parse(Rule::program, input) } pub fn span_into_string(span: Span) -> String { - span.as_str().to_string(); + span.as_str().to_string() } impl StoffelLangParser { diff --git a/compiler/src/parser/stoffel_lang.pest b/compiler/src/stoffel_lang.pest similarity index 100% rename from compiler/src/parser/stoffel_lang.pest rename to compiler/src/stoffel_lang.pest From 49f9c9095f183f7141800647e55891f010eea48e Mon Sep 17 00:00:00 2001 From: Mikerah Date: Sat, 11 Jun 2022 19:24:52 -0400 Subject: [PATCH 26/26] Applied clippy suggestions --- compiler/src/parser/mod.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/compiler/src/parser/mod.rs b/compiler/src/parser/mod.rs index 8fc5536..6dda4dc 100644 --- a/compiler/src/parser/mod.rs +++ b/compiler/src/parser/mod.rs @@ -1,8 +1,8 @@ extern crate pest; -use std::{fs, path::Path}; +use std::{path::Path}; use pest::{Parser, iterators::Pairs, error::Error, Span}; -use from_pest::FromPest; + use pest_ast::FromPest; pub mod errors; @@ -94,11 +94,11 @@ pub fn span_into_string(span: Span) -> String { impl StoffelLangParser { /// Reads file into string. - pub fn load_file(file_path: &Path) -> Result { + pub fn load_file(_file_path: &Path) -> Result { todo!(); } - pub fn parse_file(input_file: &str) -> Result { + pub fn parse_file(_input_file: &str) -> Result { todo!(); } } \ No newline at end of file