Browse Source

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

spesk 2 years ago
parent
commit
c193ede95f
5 changed files with 166 additions and 46 deletions
  1. 8 26
      example.modmark
  2. 8 0
      foo.module
  3. 32 0
      kick_drum.modmark
  4. 9 9
      maths.module
  5. 109 11
      pl_proto.pl

+ 8 - 26
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

+ 8 - 0
foo.module

@@ -0,0 +1,8 @@
+# Foo Module
+Manufacturer: Foobar
+Module: FooMod
+Revision: 1
+- Input: FooInput
+- Input: FooInput2
+-- Position: [1-2]
+- Output: FooOutput

+ 32 - 0
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

+ 9 - 9
example.module → 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

+ 109 - 11
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}->();
 		}