feat: add simple check command

This commit is contained in:
rvcas 2022-10-04 17:03:21 -04:00 committed by Lucas
parent 6ef8ba5c35
commit 6de41e64be
7 changed files with 57 additions and 68 deletions

1
Cargo.lock generated
View File

@ -26,6 +26,7 @@ dependencies = [
name = "aiken"
version = "0.0.18"
dependencies = [
"aiken-lang",
"anyhow",
"clap",
"hex",

View File

@ -20,3 +20,4 @@ pallas-traverse = "0.14.0-alpha.3"
serde = { version = "1.0.144", features = ["derive"] }
serde_json = "1.0.85"
uplc = { path = '../uplc', version = "0.0.18" }
aiken-lang = { path = "../lang", version = "0.0.17" }

View File

@ -9,6 +9,11 @@ use clap::{Parser, Subcommand};
pub enum Args {
/// Build an aiken project
Build,
/// Check a file or project
Check {
/// Specific aiken file to check
input: Option<PathBuf>,
},
/// Start a development server
Dev,
/// Create a new aiken project

View File

@ -33,6 +33,21 @@ fn main() -> anyhow::Result<()> {
todo!()
}
Args::Check { input } => {
if let Some(input) = input {
let src = fs::read_to_string(&input)?;
match aiken_lang::parser::script(&src) {
Ok(_) => (),
Err(errs) => {
for err in errs {
eprintln!("{:#?}", err);
}
}
}
}
}
Args::Dev => {
// launch a development server
// this should allow people to test

View File

@ -2,12 +2,26 @@ use chumsky::prelude::*;
use vec1::Vec1;
use crate::{
ast::{self, BinOp, Span, TodoKind, CAPTURE_VARIABLE},
ast::{self, BinOp, Span, SrcId, TodoKind, CAPTURE_VARIABLE},
error::ParseError,
expr,
expr, lexer,
token::Token,
};
pub fn script(src: &str) -> Result<ast::UntypedModule, Vec<ParseError>> {
let len = src.chars().count();
let span = |i| Span::new(SrcId::empty(), i..i + 1);
let tokens = lexer::lexer().parse(chumsky::Stream::from_iter(
span(len),
src.chars().enumerate().map(|(i, c)| (c, span(i))),
))?;
module_parser(ast::ModuleKind::Script)
.parse(chumsky::Stream::from_iter(span(len), tokens.into_iter()))
}
pub fn module_parser(
kind: ast::ModuleKind,
) -> impl Parser<Token, ast::UntypedModule, Error = ParseError> {
@ -86,6 +100,7 @@ pub fn data_parser() -> impl Parser<Token, ast::UntypedDefinition, Error = Parse
location: span,
})
.separated_by(just(Token::Comma))
.allow_trailing()
.delimited_by(just(Token::LeftParen), just(Token::RightParen));
let constructors = select! {Token::UpName { name } => name}
@ -828,6 +843,7 @@ pub fn labeled_constructor_type_args(
location: span,
})
.separated_by(just(Token::Comma))
.allow_trailing()
.delimited_by(just(Token::LeftBrace), just(Token::RightBrace))
}

17
examples/syntax.ak Normal file
View File

@ -0,0 +1,17 @@
use aiken/context.{ScriptContext}
pub type Datum {
something: String,
}
pub type Redeemer {
Buy
Sell
}
pub fn validate(datum: Datum, rdmr: Redeemer, ctx: ScriptContext) -> Bool {
when rdmr is {
Buy -> True
Sell -> datum.something == "Aiken"
}
}

View File

@ -1,66 +0,0 @@
// imports
use std/address.Address as A // alias
use std/list.{map, foldl} // access module members in one import
// `///` used for document generation
// Records (single constructor `data` type)
pub type Datum {
signer: Address,
}
// above is suger for
pub type Datum {
Datum { signer: Address },
}
// type aliases
type A = Address
// multiple constructors and a `generic`
pub type Redeemer(a) {
// records wrapped in parens
Buy(Address, a),
// records wrapped in curlies
Sell { address: Address, some_thing: a },
}
pub fn main(datum: Datum, redeemer: Redeemer, ctx: ScriptContext) {
[1, 2, 3]
|> list.map(fn(x) -> x + 1)
}
// named and anonymous functions
fn(x) -> x + 1
fn add_one(x) -> x + 1
fn(x: Int) -> x + 1
fn add_one(label x: Int) -> x + 1
fn(x: Int) {
x + 1
}
fn(x: Int) -> Int {
x + 1
}
fn add_one(x: Int) -> Int {
x + 1
}
// can be curried
fn add(a, b) {
a + 1
}
let add_one = add(1)
// matching
when redeemer is {
Buyer(address, thing) -> do_stuff(),
Seller { address, some_thing } -> do_seller_stuff(),
}