c193ede95fcaa216768bdcf89aee2a71645eeacb
commit c193ede95fcaa216768bdcf89aee2a71645eeacb
Author: spesk <spesk@pm.me>
Date: Fri Mar 18 16:10:58 2022 -0400

Cleaning thing up. Have most of the AST done, just need to handle connect

diff --git a/example.modmark b/example.modmark
index 0f96ae6..7bc15a8 100644
--- a/example.modmark
+++ b/example.modmark
@@ -1,32 +1,14 @@
-#lang reader modmark_br.rkt
-# Patch Spec
-# Representing an approximation of
-# a 909 kick. Module specs are imported
-# but don't yet exist
+# Foo Patch
+Title: Foo

-Title: Kick Drum
+ModuleDir "/home/swatson/Repos/modmark/"

-# By default "./modules" is included in the module path
-ModuleDir "/home/swatson/Repos/modular-markup/"
-
-import Module::BlueLantern::AsteroidOperatorVCF as VCF
+import Module::Foobar::FooMod
import Module::MakeNoise::Maths
-import Module::ALM::TangleQuartet as VCA
-import Module::Generic::Output
-
-set VCF.Pluck = on
-set VCF.Freq.position = 7

-set Maths.Cycle[1] = on
-set Maths.Rise[1].position = 7
-set Maths.Fall[1].position = 1
+set Maths.Cycle1 = on
+set Maths.Rise1.position = 7
+set Maths.Fall1.position = 1
set Maths.LogExp.position = 5

-set VCA.Input1.position = 5
-
-# Output of Maths env into VCF freq modulation
-connect Maths.1f VCF.PluckMod
-# Output of VCF into VCA
-connect VCF.Output.Overdrive VCA.Input1
-# VCA into soundcard/output
-connect VCA.Input1 Output.1
+connect Maths.1f FooMod.FooInput
diff --git a/foo.module b/foo.module
new file mode 100644
index 0000000..a6332db
--- /dev/null
+++ b/foo.module
@@ -0,0 +1,8 @@
+# Foo Module
+Manufacturer: Foobar
+Module: FooMod
+Revision: 1
+- Input: FooInput
+- Input: FooInput2
+-- Position: [1-2]
+- Output: FooOutput
\ No newline at end of file
diff --git a/kick_drum.modmark b/kick_drum.modmark
new file mode 100644
index 0000000..10b9eb8
--- /dev/null
+++ b/kick_drum.modmark
@@ -0,0 +1,32 @@
+#lang reader modmark_br.rkt
+# Patch Spec
+# Representing an approximation of
+# a 909 kick. Module specs are imported
+# but don't yet exist
+
+Title: Kick Drum
+
+# By default "./modules" is included in the module path
+ModuleDir "/home/swatson/Repos/modmark/"
+
+import Module::BlueLantern::AsteroidOperatorVCF as VCF
+import Module::MakeNoise::Maths
+import Module::ALM::TangleQuartet as VCA
+import Module::Generic::Output
+
+set VCF.Pluck = on
+set VCF.Freq.position = 7
+
+set Maths.Cycle[1] = on
+set Maths.Rise[1].position = 7
+set Maths.Fall[1].position = 1
+set Maths.LogExp.position = 5
+
+set VCA.Input1.position = 5
+
+# Output of Maths env into VCF freq modulation
+connect Maths.1f VCF.PluckMod
+# Output of VCF into VCA
+connect VCF.Output.Overdrive VCA.Input1
+# VCA into soundcard/output
+connect VCA.Input1 Output.1
diff --git a/example.module b/maths.module
similarity index 69%
rename from example.module
rename to maths.module
index 1bd1c8d..0aa0cac 100644
--- a/example.module
+++ b/maths.module
@@ -8,27 +8,27 @@ Revision: null
- Input: Trig1
- Input: Trig2
- Input: Attenuveter1
--- Position: [7-12],[1-5]
+-- Position: [1-12]
- Input: Attenuveter2
--- Position: [7-12],[1-5]
+-- Position: [1-12]
- Input: Attenuveter3
--- Position: [7-12],[1-5]
+-- Position: [1-12]
- Input: Attenuveter4
--- Position: [7-12],[1-5]
+-- Position: [1-12]
- Input: Rise1
--- Position: [7-12],[1-5]
+-- Position: [1-12]
- Input: Rise2
--- Position: [7-12],[1-5]
+-- Position: [1-12]
- Input: Both1
- Input: Both2
- Input: Fall1
--- Position: [7-12],[1-5]
+-- Position: [1-12]
- Input: Fall2
--- Position: [7-12],[1-5]
+-- Position: [1-12]
- Input: Cycle1
- Input: Cycle2
- Knob: LogExp
--- Position: [7-12],[1-5]
+-- Position: [1-12]
- Button: Cycle1
- Button: Cycle2
- Output: 1f
diff --git a/pl_proto.pl b/pl_proto.pl
index 6d40c24..60bb6f3 100755
--- a/pl_proto.pl
+++ b/pl_proto.pl
@@ -118,11 +118,14 @@ my %PARSE_TABLE = (
'title' => '^Title: (.*)$',
'mod_path' => '^ModuleDir\ "(.*)"$',
'import' => '^import (Module)::([a-zA-Z0-9]{1,})::([a-zA-Z0-9]{1,})(.*$)',
- 'set' => '^set\ (.*)$',
+ 'set' => '^set\ (.*)$',
+ 'connect' => '^connect(.*)$',
);

my %PARSE_RULES = (
- 'comment' => sub {},
+ 'comment' => sub {
+ # Do nothing, throw this line out
+ },
'title' => sub {
my $title = shift;
$AST{'Title'} = $title;
@@ -136,14 +139,21 @@ my %PARSE_RULES = (
push(@module_library_paths, $file_path);
},
'import' => sub {
- my $module_path = shift;
+ my $module_import = shift;
+ my $import_manu = shift;
+ my $import_mod = shift;
+ my $import_as = shift;
my @module_files = sub {
my @files;
foreach my $path ( @module_library_paths ) {
my @f = split("\n", `find $path`);
foreach my $file ( @f ) {
if ( $file =~ m/.module$/ ) {
- push(@files, $file);
+ my $f_bn = `basename $file`;
+ chomp $f_bn;
+ if ( ! grep(/$f_bn/, @files) ) {
+ push(@files, $file);
+ }
}
}
}
@@ -153,18 +163,103 @@ my %PARSE_RULES = (
my $mod_file_content = read_to_var($mod_file);
my $mod_ref = parse_module_file($mod_file_content);

- foreach my $ref ( @{$AST{'Modules'}} ) {
- if ( $$mod_ref{'Manufacturer'} eq $$ref{'Manufacturer'} &&
- $$mod_ref{'Rev'} eq $$ref{'Rev'} ) {
- # We've already imported this module
- next;
+ if ( $import_mod eq $$mod_ref{'Module'} ) {
+
+ if ( defined $AST{'Modules'} ) {
+ my $r = grep { $import_mod eq $_->{'Module'} } @{$AST{'Modules'}};
+ if ( $r == 0 ) {
+ push(@{$AST{'Modules'}}, $mod_ref);
+ }
} else {
push(@{$AST{'Modules'}}, $mod_ref);
}
+ } else {
+ next;
+ }
+ }
+ },
+ 'set' => sub {
+ my $set_line = shift;
+ my $mod_to_set;
+ my $attr_to_set;
+ my $attr_param;
+ my $value;
+ my $setter = sub {
+ my $mod_to_set = shift;
+ my $attr_to_set = shift;
+ my $attr_param = shift;
+ if ( $attr_param eq "position" ) {
+ $attr_param = "pos";
+ }
+ my $value = shift;
+
+ my %set_params = (
+ 'Param' => $attr_param,
+ 'Value' => $value,
+ );
+
+ # Check values against mod definition
+ # Pull mod ref out of AST for straight forward checking
+ my $mod_ref;
+ # Check we have module in AST
+ my $r = grep { $mod_to_set eq $_->{'Module'} } @{$AST{'Modules'}};
+ if ( $r eq 0 ) {
+ die "Can't set value on module that is not imported: $mod_to_set\n";
+ } else {
+ foreach my $module_ref ( @{$AST{'Modules'}} ) {
+ if ( $mod_to_set eq $$module_ref{'Module'} ) {
+ $mod_ref = $module_ref;
+ last;
+ }
+ }
+ }
+
+ # Check that module has param we want to set
+ if ( ! $attr_to_set eq $$mod_ref{'Inputs'}->{$attr_to_set} ) {
+ die "Can't set a param that doesn't existing in the module spec: $attr_to_set";
+ }
+
+ # If the set has an attr param, check that it's in the allowed range on the attr
+ if ( $attr_param ne "null" ) {
+ my $attr_range = $$mod_ref{'Inputs'}->{$attr_to_set}->{'pos'};
+ if ( $attr_range =~ m/([0-9]{1,2})\-([0-9]{1,2})/ ) {
+ my $r_begin = $1;
+ my $r_end = $2;
+ if ( $value > $r_end || $value < $r_begin ) {
+ die "Parse error: attr_param value: $value for $attr_to_set : $attr_param is outside of range: $r_begin $r_end";
+ }
+ } else {
+ die "Somehow encountered parse error in setter for module file $$mod_ref{'Module'}\n";
+ }
}
+
+ $AST{'Sets'}->{$mod_to_set}->{$attr_to_set} = \%set_params;
+ };
+
+ if ( $set_line =~ m/(^[A-Z]{1}[a-z]{1,})\.{1}([A-Za-z0-9]{1,})\ \=\ (.*)$/ ) {
+ $mod_to_set = $1;
+ $attr_to_set = $2;
+ $value = $3;
+ } elsif ( $set_line =~ m/(^[A-Z]{1}[a-z]{1,})\.{1}([A-Za-z0-9]{1,})\.([A-Za-z0-9]{1,})\ \=\ (.*)$/ ) {
+ $mod_to_set = $1;
+ $attr_to_set = $2;
+ $attr_param = $3;
+ $value = $4;
+ } else {
+ die "Parse error at $set_line";
}
+
+ if ( ! defined $attr_param || $attr_param eq "" ) {
+ $attr_param = "null",
+ };
+
+ $setter->($mod_to_set,$attr_to_set,$attr_param,$value);
+ },
+ 'connect' => sub {
+ my $connect_line = shift;
+ $connect_line = trim($connect_line);
},
- 'set' => sub { print("$_[0]\n"); },
+
);

# Basic line parser
@@ -179,8 +274,11 @@ sub line_parse($) {
}

if ( $line_type ne "null" && $line =~ m/$PARSE_TABLE{$line_type}/) {
- if ( defined $1 ) {
+ if ( defined $1 && ! defined $2 ) {
$PARSE_RULES{$line_type}->($1);
+ } elsif ( defined $1 && defined $2 && defined $3 && defined $4 ) {
+ # This is for `import`
+ $PARSE_RULES{$line_type}->($1,$2,$3,$4);
} else {
$PARSE_RULES{$line_type}->();
}