Skip to content

Commit

Permalink
Add helper traits to handle deref & borrow and auto-derive common traits
Browse files Browse the repository at this point in the history
  • Loading branch information
antoniusnaumann committed Jan 5, 2024
1 parent 6da9645 commit 8622292
Show file tree
Hide file tree
Showing 20 changed files with 113 additions and 25 deletions.
2 changes: 1 addition & 1 deletion example-code/functions/function_call.galvan
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ multi(vec![
// TODO: Only insert & around expressions for non-copy types
"
pub fn multiply(a: i64, b: i64) -> i64 { }
pub fn double(a: i64) -> i64 { multiply(&(a), &(2)) }
pub fn double(a: i64) -> i64 { multiply(&(&a).__borrow(), &(2)) }
"
*/

Expand Down
1 change: 1 addition & 0 deletions example-code/functions/member_function.galvan
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ multi(vec![

/*# TRANSPILE
"
#[derive(Clone, Debug, PartialEq)]
pub(crate) struct Dog;
impl Dog {
pub(crate) fn woof(&self) { }
Expand Down
1 change: 1 addition & 0 deletions example-code/functions/mut_param_function.galvan
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ multi(vec![

/*# TRANSPILE
"
#[derive(Clone, Debug, PartialEq)]
pub(crate) struct Dog;
pub(crate) fn bark(dog: &mut Dog) { }
"
Expand Down
1 change: 1 addition & 0 deletions example-code/functions/ref_param_function.galvan
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ multi(vec![

/*# TRANSPILE
"
#[derive(Clone, Debug, PartialEq)]
pub(crate) struct Dog;
pub(crate) fn bark(dog: std::sync::Arc<std::sync::Mutex<Dog>>) { }
"
Expand Down
2 changes: 1 addition & 1 deletion example-code/types/empty_struct_type.galvan
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ single(struct_type(inherited(), "EmptyStruct", vec![]))
*/

/*# TRANSPILE
"pub(crate) struct EmptyStruct { }"
"#[derive(Clone, Debug, PartialEq)] pub(crate) struct EmptyStruct { }"
*/

type EmptyStruct {}
2 changes: 1 addition & 1 deletion example-code/types/empty_tuple_type.galvan
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ single(tuple_type(inherited(), "EmptyTuple", vec![]))
*/

/*# TRANSPILE
"pub(crate) struct EmptyTuple();"
"#[derive(Clone, Debug, PartialEq)] pub(crate) struct EmptyTuple();"
*/

type EmptyTuple()
2 changes: 1 addition & 1 deletion example-code/types/empty_type.galvan
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ single(empty_type(inherited(), "EmptyMarker"))
*/

/*# TRANSPILE
"pub(crate) struct EmptyMarker;"
"#[derive(Clone, Debug, PartialEq)] pub(crate) struct EmptyMarker;"
*/

type EmptyMarker
2 changes: 1 addition & 1 deletion example-code/types/optional_dict.galvan
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ single(
*/

/*# TRANSPILE
"pub(crate) struct Foo {
"#[derive(Clone, Debug, PartialEq)] pub(crate) struct Foo {
pub(crate) bar: Option<std::collections::HashMap<String, String>>
}"
*/
Expand Down
2 changes: 1 addition & 1 deletion example-code/types/ref_type.galvan
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ single(struct_type(inherited(), "WithRef", vec![ref_struct_member("ref_member",
*/

/*# TRANSPILE
"pub(crate) struct WithRef {
"#[derive(Clone, Debug, PartialEq)] pub(crate) struct WithRef {
pub(crate) ref_member: std::sync::Arc<std::sync::Mutex<String>>
}"
*/
Expand Down
2 changes: 1 addition & 1 deletion example-code/types/simple_struct_type.galvan
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ single(struct_type(public(), "SimpleStruct", vec![struct_member("member", plain(
*/

/*# TRANSPILE
"pub struct SimpleStruct {
"#[derive(Clone, Debug, PartialEq)] pub struct SimpleStruct {
pub(crate) member: String
}"
*/
Expand Down
2 changes: 1 addition & 1 deletion example-code/types/simple_tuple_type.galvan
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ single(tuple_type(public(), "SimpleTuple", vec![tuple_member(plain("Int")), tupl
*/

/*# TRANSPILE
"pub struct SimpleTuple(i64, i64);"
"#[derive(Clone, Debug, PartialEq)] pub struct SimpleTuple(i64, i64);"
*/

pub type SimpleTuple(Int, Int)
1 change: 1 addition & 0 deletions galvan-ast/src/item/type.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ pub struct StructTypeDecl {
pub ident: TypeIdent,
pub members: Vec<StructTypeMember>,
}

#[derive(Debug, PartialEq, Eq, FromPest)]
#[pest_ast(rule(Rule::struct_field))]
pub struct StructTypeMember {
Expand Down
2 changes: 1 addition & 1 deletion galvan-transpiler/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ fn transpile_segmented(
let lib = TranspileOutput {
file_name: galvan_module!("rs").into(),
content: format!(
"pub(crate) mod {} {{\n{}\nuse crate::*;\n{}\n}}",
"extern crate galvan; pub(crate) use ::galvan::std::*;\n pub(crate) mod {} {{\n{}\nuse crate::*;\n{}\n}}",
galvan_module!(),
SUPPRESS_WARNINGS,
[modules, toplevel_functions, &main].join("\n\n")
Expand Down
18 changes: 7 additions & 11 deletions galvan-transpiler/src/transpile_item/assignment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,36 +8,32 @@ impl_transpile_variants!(AssignmentTarget; Ident, MemberFieldAccess);
impl Transpile for Assignment {
fn transpile(&self, ctx: &Context) -> String {
// TODO: Use scope to determine if variable is &mut or owned, dereference is only needed for &mut
let deref = match self.target {
AssignmentTarget::Ident(_) => "*",
AssignmentTarget::MemberFieldAccess(_) => "",
};
let Self {
target,
operator,
expression: exp,
} = self;
match operator {
AssignmentOperator::Assign => {
transpile!(ctx, "{deref}{} = {}", target, exp)
transpile!(ctx, "*({}.__mut()) = {}", target, exp)
}
AssignmentOperator::AddAssign => {
transpile!(ctx, "{deref}{} += {}", target, exp)
transpile!(ctx, "*({}.__mut()) += {}", target, exp)
}
AssignmentOperator::SubAssign => {
transpile!(ctx, "{deref}{} -= {}", target, exp)
transpile!(ctx, "*({}.__mut()) -= {}", target, exp)
}
AssignmentOperator::MulAssign => {
transpile!(ctx, "{deref}{} *= {}", target, exp)
transpile!(ctx, "*({}.__mut()) *= {}", target, exp)
}
AssignmentOperator::DivAssign => {
transpile!(ctx, "{deref}{} /= {}", target, exp)
transpile!(ctx, "*({}.__mut()) /= {}", target, exp)
}
AssignmentOperator::RemAssign => {
transpile!(ctx, "{deref}{} %= {}", target, exp)
transpile!(ctx, "*({}.__mut()) %= {}", target, exp)
}
AssignmentOperator::PowAssign => {
transpile!(ctx, "{deref}{} = {}.pow({})", target, target, exp)
transpile!(ctx, "*({}.__mut()) = {}.pow({})", target, target, exp)
}
}
}
Expand Down
3 changes: 3 additions & 0 deletions galvan-transpiler/src/transpile_item/function_call.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ impl Transpile for FunctionCallArg {
(Mod::Let, _) => {
todo!("TRANSPILER ERROR: Let modifier is not allowed for function call arguments")
}
(Mod::Inherited, expr @ Exp::Ident(_)) => {
transpile!(ctx, "&(&{}).__borrow()", expression)
}
(Mod::Inherited, expression) => {
transpile!(ctx, "&({})", expression)
}
Expand Down
14 changes: 12 additions & 2 deletions galvan-transpiler/src/transpile_item/statement.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,17 +36,27 @@ impl Transpile for Declaration {
// TODO: Clone inner type from ref types to non-ref types
self.expression
.as_ref()
.map(|expr| transpile_assignment_expression(ctx, keyword, expr))
.map(|expr| transpile_assignment_expression(ctx, expr))
.map(|expr| {
if self.decl_modifier == DeclModifier::Ref {
format!("(&({expr})).__to_ref()")
} else {
expr
}
})
.map(|expr| format!("{keyword} {identifier}{ty} = {expr}"))
.unwrap_or_else(|| format!("{keyword} {identifier}{ty}"))
}
}

fn transpile_assignment_expression(ctx: &Context, keyword: &str, expr: &Expression) -> String {
fn transpile_assignment_expression(ctx: &Context, expr: &Expression) -> String {
match expr {
Expression::Ident(ident) => {
transpile!(ctx, "{}.to_owned()", ident)
}
Expression::MemberFieldAccess(access) => {
transpile!(ctx, "{}.to_owned()", access)
}
expr => expr.transpile(ctx),
}
}
Expand Down
8 changes: 5 additions & 3 deletions galvan-transpiler/src/transpile_item/struct.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,13 @@ use crate::macros::{impl_transpile, impl_transpile_match, transpile};
use crate::{StructTypeMember, Transpile, TupleTypeMember, TypeDecl};
use galvan_ast::DeclModifier;

static DERIVE: &str = "#[derive(Clone, Debug, PartialEq)]";

impl_transpile_match! { TypeDecl,
Tuple(def) => ("{} struct {}({});", def.visibility, def.ident, def.members),
Struct(def) => ("{} struct {} {{\n{}\n}}", def.visibility, def.ident, def.members),
Tuple(def) => ("{DERIVE} {} struct {}({});", def.visibility, def.ident, def.members),
Struct(def) => ("{DERIVE} {} struct {} {{\n{}\n}}", def.visibility, def.ident, def.members),
Alias(def) => ("{} type {} = {};", def.visibility, def.ident, def.r#type),
Empty(def) => ("{} struct {};", def.visibility, def.ident),
Empty(def) => ("{DERIVE} {} struct {};", def.visibility, def.ident),
}

impl_transpile!(TupleTypeMember, "{}", r#type);
Expand Down
2 changes: 2 additions & 0 deletions galvan-transpiler/tests/test_transpilation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,14 @@ mod test_utils {
.join("\n\n")
.lines()
.filter(|line| {
let line = line.trim();
!line.starts_with("pub use")
&& !line.starts_with("use")
&& !line.starts_with("mod")
&& !line.starts_with("pub(crate) mod")
&& !line.starts_with("pub mod")
&& !line.starts_with("#![")
&& !line.starts_with("extern crate galvan")
})
.dropping_back(1)
.collect::<Vec<_>>()
Expand Down
2 changes: 2 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
pub mod std;

pub use galvan_transpiler::galvan_module;

#[cfg(feature = "build")]
Expand Down
69 changes: 69 additions & 0 deletions src/std.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
use std::borrow::{Borrow, BorrowMut};
use std::ops::Deref;
use std::sync::{Arc, Mutex, MutexGuard};

pub trait __ToRef {
type Inner;
fn __to_ref(&self) -> Arc<Mutex<Self::Inner>>;
}

impl<T: ToOwned> __ToRef for &T {
type Inner = T::Owned;

#[inline(always)]
fn __to_ref(&self) -> Arc<Mutex<Self::Inner>> {
Arc::new(Mutex::new(self.deref().to_owned()))
}
}

impl<T> __ToRef for Arc<Mutex<T>> {
type Inner = T;

#[inline(always)]
fn __to_ref(&self) -> Arc<Mutex<Self::Inner>> {
Arc::clone(self)
}
}

pub trait __Borrow<'a> {
type Inner;
fn __borrow(&'a self) -> Self::Inner;
}

impl<'a, T: Borrow<T>> __Borrow<'a> for &'a T {
type Inner = &'a T;
#[inline(always)]
fn __borrow(&'a self) -> Self::Inner {
(**self).borrow()
}
}

impl<'a, T: 'a> __Borrow<'a> for Arc<Mutex<T>> {
type Inner = MutexGuard<'a, T>;
#[inline(always)]
fn __borrow(&'a self) -> Self::Inner {
self.lock().unwrap()
}
}

impl<'a, T: 'a> __Borrow<'a> for MutexGuard<'a, T> {
type Inner = &'a T;
#[inline(always)]
fn __borrow(&'a self) -> Self::Inner {
(*self).deref()
}
}

pub trait __Mut<'a> {
type Inner;

fn __mut(&'a mut self) -> Self::Inner;
}

impl<'a, T: BorrowMut<T> + 'a> __Mut<'a> for T {
type Inner = &'a mut T;

fn __mut(&'a mut self) -> Self::Inner {
self.borrow_mut()
}
}

0 comments on commit 8622292

Please sign in to comment.