Skip to content

Commit

Permalink
Merge pull request #94 from sezna/alex/playground-updates
Browse files Browse the repository at this point in the history
[DRAFT] Add stdlib and update playground
  • Loading branch information
sezna authored Jul 7, 2024
2 parents e6b030a + a5ff1c2 commit 0820d40
Show file tree
Hide file tree
Showing 24 changed files with 204 additions and 81 deletions.
8 changes: 0 additions & 8 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,6 @@ env:
RUSTFLAGS: "-Dwarnings"

jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Machete
uses: bnjbvr/cargo-machete@main

clippy_check:
runs-on: ubuntu-latest
steps:
Expand Down
6 changes: 6 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,4 @@ members = [
"petr-profiling",
"petr-api",
"petr-playground"
]
, "stdlib"]
43 changes: 25 additions & 18 deletions pete/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use std::{
use clap::Parser as ClapParser;
use petr_api::*;
use petr_pkg::BuildPlan;
use petr_resolve::Dependency;
use termcolor::{ColorChoice, ColorSpec, StandardStream, WriteColor};

pub mod error {
Expand Down Expand Up @@ -189,7 +190,13 @@ pub fn compile(
let name = Identifier {
id: interner.insert(Rc::from(item.manifest.name)),
};
dependencies.push((item.key, name, item.depends_on, ast));

dependencies.push(Dependency {
key: item.key,
name,
dependencies: item.depends_on,
ast,
});
}

timings.end("parse dependencies");
Expand Down Expand Up @@ -257,25 +264,25 @@ pub fn load_project_and_dependencies(path: &Path) -> Result<(petr_pkg::Lockfile,
Ok((lockfile, files, build_plan))
}

pub fn load_files(path: &Path) -> Vec<(PathBuf, String)> {
let mut buf = Vec::new();

fn read_petr_files(
dir: &PathBuf,
buf: &mut Vec<(PathBuf, String)>,
) {
let entries = fs::read_dir(dir).expect("Failed to read directory");
for entry in entries {
let entry = entry.expect("Failed to read directory entry");
let path = entry.path();
if path.is_dir() {
read_petr_files(&path, buf);
} else if path.extension().and_then(|s| s.to_str()) == Some("pt") {
let source = fs::read_to_string(&path).expect("Failed to read file");
buf.push((path, source));
}
fn read_petr_files(
dir: &PathBuf,
buf: &mut Vec<(PathBuf, String)>,
) {
let entries = fs::read_dir(dir).expect("Failed to read directory");
for entry in entries {
let entry = entry.expect("Failed to read directory entry");
let path = entry.path();
if path.is_dir() {
read_petr_files(&path, buf);
} else if path.extension().and_then(|s| s.to_str()) == Some("pt") {
let source = fs::read_to_string(&path).expect("Failed to read file");
buf.push((path, source));
}
}
}

pub fn load_files(path: &Path) -> Vec<(PathBuf, String)> {
let mut buf = Vec::new();

read_petr_files(&path.join("src"), &mut buf);
buf
Expand Down
18 changes: 15 additions & 3 deletions petr-api/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,19 @@
//! Top-level API for the petr programming language.
//! Exposes relevant APIs from all compiler stages and tooling.
pub use petr_fmt::{format_sources, FormatterConfig};
#[cfg(not(feature = "no_std"))]
use std::{
fs,
path::{Path, PathBuf},
rc::Rc,
};

pub use petr_fmt::{format_sources, Formattable, FormatterConfig, FormatterContext};
pub use petr_ir::Lowerer;
pub use petr_parse::Parser;
#[cfg(not(feature = "no_std"))]
pub use petr_pkg::{manifest::find_manifest, BuildPlan};
pub use petr_resolve::resolve_symbols;
pub use petr_resolve::{resolve_symbols, Dependency};
pub use petr_typecheck::type_check;
pub use petr_utils::{render_error, Identifier, IndexMap, SourceId, SpannedItem};
pub use petr_vm::Vm;
Expand Down Expand Up @@ -149,7 +156,12 @@ pub fn compile(
let name = Identifier {
id: interner.insert(Rc::from(item.manifest.name)),
};
dependencies.push((item.key, name, item.depends_on, ast));
dependencies.push(petr_resolve::Dependency {
key: item.key,
name,
dependencies: item.depends_on,
ast,
});
}

timings.end("parse dependencies");
Expand Down
14 changes: 14 additions & 0 deletions petr-ast/src/dependency.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
use crate::Ast;

/// Describes the AST of a dependency package
pub struct Dependency {
/// The unique key that identifies this source package, agnostic of the alias given to it in
/// the manifest file
pub key: String,
/// The name of the package as given in the manifest file
pub name: petr_utils::Identifier,
/// The keys of any packages that this package depends on
pub dependencies: Vec<String>,
/// The AST of the source code of this package
pub ast: Ast,
}
1 change: 1 addition & 0 deletions petr-ast/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
mod ast;
mod comments;
pub mod dependency;
mod pretty_print;
pub use ast::*;
pub use comments::*;
31 changes: 20 additions & 11 deletions petr-bind/src/binder.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::collections::BTreeMap;

use petr_ast::{Ast, Binding, ExprId, Expression, FunctionDeclaration, Ty, TypeDeclaration};
use petr_ast::{dependency::Dependency, Ast, Binding, ExprId, Expression, FunctionDeclaration, Ty, TypeDeclaration};
use petr_utils::{idx_map_key, Identifier, IndexMap, Path, SymbolId};
// TODO:
// - i don't know if type cons needs a scope. Might be good to remove that.
Expand Down Expand Up @@ -102,7 +102,10 @@ impl<T> Scope<T> {
k: SymbolId,
v: T,
) {
self.items.insert(k, v);
// TODO: error handling and/or shadowing rules for this
if self.items.insert(k, v).is_some() {
todo!("throw error for overriding symbol name {k}")
}
}

pub fn parent(&self) -> Option<ScopeId> {
Expand Down Expand Up @@ -336,18 +339,17 @@ impl Binder {

pub fn from_ast_and_deps(
ast: &Ast,
// TODO better type here
dependencies: Vec<(
/* Key */ String,
/*Name from manifest*/ Identifier,
/*Things this depends on*/ Vec<String>,
Ast,
)>,
dependencies: Vec<Dependency>,
) -> Self {
let mut binder = Self::new();

for dependency in dependencies {
let (_key, name, _depends_on, dep_ast) = dependency;
for Dependency {
key: _,
name,
dependencies: _,
ast: dep_ast,
} in dependencies
{
let dep_scope = binder.create_scope_from_path(&Path::new(vec![name]));
binder.with_specified_scope(dep_scope, |binder, _scope_id| {
for module in dep_ast.modules {
Expand Down Expand Up @@ -397,6 +399,13 @@ impl Binder {
) -> ScopeId {
let mut current_scope_id = self.current_scope_id();
for segment in path.iter() {
// if this scope already exists,
// just use that pre-existing ID
if let Some(Item::Module(module_id)) = self.find_symbol_in_scope(segment.id, current_scope_id) {
current_scope_id = self.modules.get(*module_id).root_scope;
continue;
}

let next_scope = self.create_scope(ScopeKind::Module(*segment));
let module = Module {
root_scope: next_scope,
Expand Down
1 change: 1 addition & 0 deletions petr-bind/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,6 @@
//! scopes define. The resolver is then able to do scope-aware name resolution in the next step.
pub use binder::{Bind, Binder, BindingId, FunctionId, Item, ModuleId, Scope, ScopeId, ScopeKind, TypeId};
pub use petr_ast::dependency::Dependency;
mod binder;
mod impls;
2 changes: 1 addition & 1 deletion petr-fmt/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ use std::{

pub use config::{FormatterConfig, FormatterConfigBuilder};
use constants::{CLOSE_COMMENT_STR, INDENTATION_CHARACTER, OPEN_COMMENT_STR};
use ctx::FormatterContext;
pub use ctx::FormatterContext;
use petr_ast::*;
use petr_parse::Parser;
use petr_utils::{render_error, PrettyPrint, SpannedItem};
Expand Down
1 change: 1 addition & 0 deletions petr-playground/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,4 @@ crate-type = ["cdylib"]
[dependencies]
wasm-bindgen = "0.2.92"
petr-api = { path = "../petr-api", default-features = false, features = ["no_std"] }
stdlib = { path = "../stdlib" }
1 change: 1 addition & 0 deletions petr-playground/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#output {
/* monospace font, smallish font */
font-family: monospace;
white-space: pre;
font-size: 0.8em;
}

Expand Down
31 changes: 25 additions & 6 deletions petr-playground/index.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import { run_snippet } from './pkg';
import { run_snippet, format } from './pkg';


import * as monaco from 'monaco-editor';
// or import * as monaco from 'monaco-editor/esm/vs/editor/editor.api';
// if shipping only a subset of the features & languages is desired
//

// config for petr as a custom language
// // Register a new language
Expand All @@ -15,7 +14,7 @@ monaco.languages.setMonarchTokensProvider("petr", {
keywords: [ 'function', 'returns', 'in' ],
tokenizer: {
root: [
[/\~[a-zA-Z][a-zA-Z0-9]*/, "function-call"],
[/\~([a-zA-Z][a-zA-Z0-9]+)(\.[a-zA-Z]([a-zA-Z0-9])+)*/, "function-call"],
[/\@[a-zA-Z]+/, "intrinsic"],
[/[0-9]+/, "integer-literal"],
[/\".*\"/, "string-literal"],
Expand All @@ -31,13 +30,13 @@ monaco.languages.setLanguageConfiguration("petr", {
autoClosingPairs: [
{ open: '[', close: ']' },
{ open: '(', close: ')' },
{ open: "'", close: "'" }
{ open: '"', close: '"' }
],
surroundingPairs: [
{ open: '{', close: '}' },
{ open: '[', close: ']' },
{ open: '(', close: ')' },
{ open: "'", close: "'" }
{ open: '"', close: '"' }
]
})

Expand All @@ -52,6 +51,7 @@ monaco.editor.defineTheme("petr-theme", {
{ token: "function-call", foreground: "808080", fontStyle: "bold" },
{ token: "string-literal", foreground: literalColor },
{ token: "integer-literal", foreground: literalColor },
{ token: "keyword", foreground: literalColor },
],
colors: {
"editor.foreground": "#ffffff",
Expand Down Expand Up @@ -111,7 +111,7 @@ monaco.languages.registerCompletionItemProvider("mySpecialLanguage", {


monaco.editor.create(document.getElementById('monaco-editor'), {
value: "function main() returns 'unit \n @puts(\"Hello, World!\")",
value: "function main() returns 'unit \n ~std.io.print \"Hello, World!\"",
language: 'petr',
theme: "petr-theme",
});
Expand All @@ -121,6 +121,12 @@ export function setOutputContent(content) {
}
window.setOutputContent = setOutputContent;

export function setCodeEditorContent(content) {
monaco.editor.getModels()[0].setValue(content);
}

window.setCodeEditorContent= setCodeEditorContent;

// set on-clicks for the buttons
document.getElementById('run').onclick = function() {
// get the text content from the monaco instance
Expand All @@ -137,3 +143,16 @@ document.getElementById('run').onclick = function() {
return;
};
}
document.getElementById('format').onclick = function() {
// get the text content from the monaco instance
let code = monaco.editor.getModels()[0].getValue();
// run the code
// TODO: actually render the errors on the span in the diagnostics of monaco
try { format(code); } catch (e) {
// set the output to the diagnostics
// because an Err result from wasm becomes an exception
// might be good to not use Result for that reason
document.getElementById('output').innerHTML = e;
return;
};
}
Loading

0 comments on commit 0820d40

Please sign in to comment.