Skip to content

Commit

Permalink
Merge pull request #29 from CertainLach/type-safety
Browse files Browse the repository at this point in the history
Jsonnet type system
  • Loading branch information
CertainLach authored Jan 25, 2021
2 parents 847c11f + c93dcb4 commit a98d285
Show file tree
Hide file tree
Showing 36 changed files with 1,776 additions and 810 deletions.
39 changes: 19 additions & 20 deletions Cargo.lock

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

4 changes: 3 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
[workspace]
members = [
"crates/jrsonnet-interner",
"crates/jrsonnet-parser",
"crates/jrsonnet-evaluator",
"crates/jrsonnet-stdlib",
"crates/jrsonnet-cli",
"crates/jrsonnet-types",
"bindings/jsonnet",
"cmds/jrsonnet"
"cmds/jrsonnet",
]

[profile.test]
Expand Down
1 change: 1 addition & 0 deletions bindings/jsonnet/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ authors = ["Yaroslav Bolyukin <[email protected]>"]
edition = "2018"

[dependencies]
jrsonnet-interner = { path = "../../crates/jrsonnet-interner", version = "0.3.3" }
jrsonnet-evaluator = { path = "../../crates/jrsonnet-evaluator", version = "0.3.3" }
jrsonnet-parser = { path = "../../crates/jrsonnet-parser", version = "0.3.3" }

Expand Down
7 changes: 4 additions & 3 deletions bindings/jsonnet/src/import.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use jrsonnet_evaluator::{
error::{Error::*, Result},
throw, EvaluationState, ImportResolver,
};
use jrsonnet_interner::IStr;
use std::{
any::Any,
cell::RefCell,
Expand All @@ -30,7 +31,7 @@ pub struct CallbackImportResolver {
cb: JsonnetImportCallback,
ctx: *mut c_void,

out: RefCell<HashMap<PathBuf, Rc<str>>>,
out: RefCell<HashMap<PathBuf, IStr>>,
}
impl ImportResolver for CallbackImportResolver {
fn resolve_file(&self, from: &PathBuf, path: &PathBuf) -> Result<Rc<PathBuf>> {
Expand Down Expand Up @@ -75,7 +76,7 @@ impl ImportResolver for CallbackImportResolver {

Ok(Rc::new(found_here_buf))
}
fn load_file_contents(&self, resolved: &PathBuf) -> Result<Rc<str>> {
fn load_file_contents(&self, resolved: &PathBuf) -> Result<IStr> {
Ok(self.out.borrow().get(resolved).unwrap().clone())
}
unsafe fn as_any(&self) -> &dyn Any {
Expand Down Expand Up @@ -124,7 +125,7 @@ impl ImportResolver for NativeImportResolver {
throw!(ImportFileNotFound(from.clone(), path.clone()))
}
}
fn load_file_contents(&self, id: &PathBuf) -> Result<Rc<str>> {
fn load_file_contents(&self, id: &PathBuf) -> Result<IStr> {
let mut file = File::open(id).map_err(|_e| ResolvedFileNotFound(id.clone()))?;
let mut out = String::new();
file.read_to_string(&mut out)
Expand Down
5 changes: 3 additions & 2 deletions bindings/jsonnet/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ pub mod vars_tlas;

use import::NativeImportResolver;
use jrsonnet_evaluator::{EvaluationState, ManifestFormat, Val};
use jrsonnet_interner::IStr;
use std::{
alloc::Layout,
ffi::{CStr, CString},
Expand Down Expand Up @@ -161,7 +162,7 @@ pub unsafe extern "C" fn jsonnet_evaluate_snippet(
})
}

fn multi_to_raw(multi: Vec<(Rc<str>, Rc<str>)>) -> *const c_char {
fn multi_to_raw(multi: Vec<(IStr, IStr)>) -> *const c_char {
let mut out = Vec::new();
for (i, (k, v)) in multi.iter().enumerate() {
if i != 0 {
Expand Down Expand Up @@ -237,7 +238,7 @@ pub unsafe extern "C" fn jsonnet_evaluate_snippet_multi(
})
}

fn stream_to_raw(multi: Vec<Rc<str>>) -> *const c_char {
fn stream_to_raw(multi: Vec<IStr>) -> *const c_char {
let mut out = Vec::new();
for (i, v) in multi.iter().enumerate() {
if i != 0 {
Expand Down
2 changes: 1 addition & 1 deletion bindings/jsonnet/src/native.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ pub unsafe extern "C" fn jsonnet_native_callback(

vm.add_native(
name,
Rc::new(NativeCallback::new(params, move |args| {
Rc::new(NativeCallback::new(params, move |_caller, args| {
let mut n_args = Vec::new();
for a in args {
n_args.push(Some(Box::new(a.clone())));
Expand Down
10 changes: 5 additions & 5 deletions bindings/jsonnet/src/val_extract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use std::{

#[no_mangle]
pub extern "C" fn jsonnet_json_extract_string(_vm: &EvaluationState, v: &Val) -> *mut c_char {
match v.unwrap_if_lazy().unwrap() {
match v {
Val::Str(s) => CString::new(&*s as &str).unwrap().into_raw(),
_ => std::ptr::null_mut(),
}
Expand All @@ -20,25 +20,25 @@ pub extern "C" fn jsonnet_json_extract_number(
v: &Val,
out: &mut c_double,
) -> c_int {
match v.unwrap_if_lazy().unwrap() {
match v {
Val::Num(n) => {
*out = n;
*out = *n;
1
}
_ => 0,
}
}
#[no_mangle]
pub extern "C" fn jsonnet_json_extract_bool(_vm: &EvaluationState, v: &Val) -> c_int {
match v.unwrap_if_lazy().unwrap() {
match v {
Val::Bool(false) => 0,
Val::Bool(true) => 1,
_ => 2,
}
}
#[no_mangle]
pub extern "C" fn jsonnet_json_extract_null(_vm: &EvaluationState, v: &Val) -> c_int {
match v.unwrap_if_lazy().unwrap() {
match v {
Val::Null => 1,
_ => 0,
}
Expand Down
4 changes: 2 additions & 2 deletions bindings/jsonnet/src/val_make.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//! Create values in VM
use jrsonnet_evaluator::{EvaluationState, ObjValue, Val};
use jrsonnet_evaluator::{ArrValue, EvaluationState, ObjValue, Val};
use std::{
ffi::CStr,
os::raw::{c_char, c_double, c_int},
Expand Down Expand Up @@ -38,7 +38,7 @@ pub extern "C" fn jsonnet_json_make_null(_vm: &EvaluationState) -> *mut Val {

#[no_mangle]
pub extern "C" fn jsonnet_json_make_array(_vm: &EvaluationState) -> *mut Val {
Box::into_raw(Box::new(Val::Arr(Rc::new(Vec::new()))))
Box::into_raw(Box::new(Val::Arr(ArrValue::Eager(Rc::new(Vec::new())))))
}

#[no_mangle]
Expand Down
17 changes: 11 additions & 6 deletions bindings/jsonnet/src/val_modify.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@
//! Only tested with variables, which haven't altered by code before appearing here
//! In jrsonnet every value is immutable, and this code is probally broken
use jrsonnet_evaluator::{EvaluationState, LazyBinding, LazyVal, ObjMember, ObjValue, Val};
use jrsonnet_evaluator::{
ArrValue, EvaluationState, LazyBinding, LazyVal, ObjMember, ObjValue, Val,
};
use jrsonnet_parser::Visibility;
use std::{collections::HashMap, ffi::CStr, os::raw::c_char, rc::Rc};

Expand All @@ -12,14 +14,17 @@ use std::{collections::HashMap, ffi::CStr, os::raw::c_char, rc::Rc};
#[no_mangle]
pub unsafe extern "C" fn jsonnet_json_array_append(
_vm: &EvaluationState,
arr: *mut Val,
arr: &mut Val,
val: &Val,
) {
match *Box::from_raw(arr) {
match arr {
Val::Arr(old) => {
let mut new = Rc::try_unwrap(old).expect("arr with no refs");
new.push(val.clone());
*arr = Val::Arr(Rc::new(new));
let mut new = Vec::new();
for item in old.iter_lazy() {
new.push(item);
}
new.push(LazyVal::new_resolved(val.clone()));
*arr = Val::Arr(ArrValue::Lazy(Rc::new(new)));
}
_ => panic!("should receive array"),
}
Expand Down
7 changes: 3 additions & 4 deletions crates/jrsonnet-evaluator/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,6 @@ default = ["serialized-stdlib", "faster", "explaining-traces", "serde-json"]
serialized-stdlib = ["serde", "bincode", "jrsonnet-parser/deserialize"]
# Allow to convert Val into serde_json::Value and backwards
serde-json = ["serde", "serde_json"]
# Same as above, but with generated code instead of serde. Reduces memory usage, but increases binary size and compilation time
codegenerated-stdlib = []
# Replace some standard library functions with faster implementations (I.e manifestJsonEx)
# Library works fine without this feature, but requires more memory and time for std function calls
faster = []
Expand All @@ -24,8 +22,10 @@ explaining-traces = ["annotate-snippets"]
unstable = []

[dependencies]
jrsonnet-interner = { path = "../jrsonnet-interner" }
jrsonnet-parser = { path = "../jrsonnet-parser", version = "0.3.3" }
jrsonnet-stdlib = { path = "../jrsonnet-stdlib", version = "0.3.3" }
jrsonnet-types = { path = "../jrsonnet-types", version = "0.3.3" }
pathdiff = "0.2.0"

closure = "0.3.0"
Expand Down Expand Up @@ -57,8 +57,7 @@ features = ["color"]
optional = true

[build-dependencies]
jrsonnet-parser = { path = "../jrsonnet-parser", features = ["dump", "serialize", "deserialize"], version = "0.3.3" }
jrsonnet-parser = { path = "../jrsonnet-parser", features = ["serialize", "deserialize"], version = "0.3.3" }
jrsonnet-stdlib = { path = "../jrsonnet-stdlib", version = "0.3.3" }
structdump = "0.1.2"
serde = "1.0"
bincode = "1.3.1"
21 changes: 6 additions & 15 deletions crates/jrsonnet-evaluator/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ use std::{
path::{Path, PathBuf},
rc::Rc,
};
use structdump::CodegenResult;

fn main() {
let parsed = parse(
Expand All @@ -36,11 +35,12 @@ fn main() {
name: FieldName::Fixed(name),
..
})
if **name == *"join" || **name == *"manifestJsonEx" ||
**name == *"escapeStringJson" || **name == *"equals" ||
**name == *"base64" || **name == *"foldl" || **name == *"foldr" ||
**name == *"sortImpl" || **name == *"format" || **name == *"range" ||
**name == *"reverse" || **name == *"slice" || **name == *"mod"
if name == "join" || name == "manifestJsonEx" ||
name == "escapeStringJson" || name == "equals" ||
name == "base64" || name == "foldl" || name == "foldr" ||
name == "sortImpl" || name == "format" || name == "range" ||
name == "reverse" || name == "slice" || name == "mod" ||
name == "strReplace"
)
})
.collect(),
Expand All @@ -52,15 +52,6 @@ fn main() {
} else {
parsed
};
{
let mut codegen = CodegenResult::default();
let code = codegen.codegen(&parsed);

let out_dir = env::var("OUT_DIR").unwrap();
let dest_path = Path::new(&out_dir).join("stdlib.rs");
let mut f = File::create(&dest_path).unwrap();
f.write_all(&code.as_bytes()).unwrap();
}
{
let out_dir = env::var("OUT_DIR").unwrap();
let dest_path = Path::new(&out_dir).join("stdlib.bincode");
Expand Down
13 changes: 7 additions & 6 deletions crates/jrsonnet-evaluator/src/builtin/format.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
//! faster std.format impl
#![allow(clippy::too_many_arguments)]

use crate::{error::Error::*, throw, LocError, ObjValue, Result, Val, ValType};
use crate::{error::Error::*, throw, LocError, ObjValue, Result, Val};
use jrsonnet_interner::IStr;
use jrsonnet_types::ValType;
use thiserror::Error;

#[derive(Debug, Clone, Error)]
Expand All @@ -19,7 +21,7 @@ pub enum FormatError {
#[error("mapping keys required")]
MappingKeysRequired,
#[error("no such format field: {0}")]
NoSuchFormatField(Rc<str>),
NoSuchFormatField(IStr),
}

impl From<FormatError> for LocError {
Expand All @@ -28,7 +30,6 @@ impl From<FormatError> for LocError {
}
}

use std::rc::Rc;
use FormatError::*;

type ParseResult<'t, T> = std::result::Result<(T, &'t str), FormatError>;
Expand Down Expand Up @@ -573,7 +574,7 @@ pub fn format_code(
);
}
}
ConvTypeV::Char => match value.clone().unwrap_if_lazy()? {
ConvTypeV::Char => match value.clone() {
Val::Num(n) => tmp_out.push(
std::char::from_u32(n as u32)
.ok_or_else(|| InvalidUnicodeCodepointGot(n as u32))?,
Expand All @@ -590,7 +591,7 @@ pub fn format_code(
throw!(TypeMismatch(
"%c requires number/string",
vec![ValType::Num, ValType::Str],
value.value_type()?,
value.value_type(),
));
}
},
Expand Down Expand Up @@ -679,7 +680,7 @@ pub fn format_obj(str: &str, values: &ObjValue) -> Result<String> {
}
Element::Code(c) => {
// TODO: Operate on ref
let f: Rc<str> = c.mkey.into();
let f: IStr = c.mkey.into();
let width = match c.width {
Width::Star => {
throw!(CannotUseStarWidthWithObject);
Expand Down
Loading

0 comments on commit a98d285

Please sign in to comment.