diff --git a/MATL_spec.pdf b/MATL_spec.pdf index aafaf68..428bbef 100644 Binary files a/MATL_spec.pdf and b/MATL_spec.pdf differ diff --git a/funDef.mat b/funDef.mat index 3164371..b9805cc 100644 Binary files a/funDef.mat and b/funDef.mat differ diff --git a/funDef.txt b/funDef.txt index d3187b9..196d1fa 100644 --- a/funDef.txt +++ b/funDef.txt @@ -24,10 +24,10 @@ Z! 1 1 1 1 1 1 true true out{1} = full(in{1}); convert sparse matrix to full mat X" 2 inf 3 1 1 1 true true out{1} = repmat(in{:}); replicate and tile array \matlab+repmat+ Y" 2 inf 2 1 1 1 true true out{1} = repelem(in{:}); replicate elements of array \matlab+repelem+ (run-length decoding) Z" 1 1 1 1 1 1 true true out{1} = blanks(in{1}); string of blanks \matlab+blanks+ -# 1 1 1 0 0 0 false false S_OUT = STACK{end}; STACK(end) = []; output specification specify outputs for next function +# % The numbers of inputs and outputs for # are not used by the code, but are used for generating the help file X# -Y# 1 2 1 0 0 0 true true rng(in{:}); control the random number generator \matlab+rng+ +Y# Z# 1 3 1 0 0 0 true true data = in{1}; if ~iscell(data), data = {data}; end write to file Appends first input to file \comp{inout}, creating it if necessary. If the input is an array it is converted to char and written. If the input is a cell array input, the contents of each cell are converted to char and written, with a newline (character 10) in between. With $2$ inputs: second input specifies filename; if empty defaults to \comp{inout}. With $3$ inputs: third input specifies whether any previous contents of file should be kept. sep = char(10); if numel(in)>=2 && ~isempty(in{2}), file = in{2}; else file = 'inout'; end @@ -38,7 +38,7 @@ Z# 1 3 1 0 0 0 true true data = in{1}; if ~iscell(data), data = {data}; end writ if n7 || (verNum(1)==7 && verNum(2)>=13)); if any(options=='h') if nargin>1 - matl_help(H, s, verbose, isMatlab, verNum) + matl_help(H, s, verbose, useTags) else - matl_help(H, '', verbose, isMatlab, verNum) + matl_help(H, '', verbose, useTags) end return end @@ -214,7 +215,7 @@ function matl(varargin) if verbose disp('Parsing program') end - S = matl_parse(s); + S = matl_parse(s, useTags); if verbose if numel(S)~=1 fprintf(' %i statements parsed\n', numel(S)) @@ -239,7 +240,7 @@ function matl(varargin) if verbose disp('Compiling program') end - S = matl_compile(S, F, L, pOutFile, cOutFile, verbose, isMatlab); + S = matl_compile(S, F, L, pOutFile, cOutFile, verbose, isMatlab, useTags); %if verbose % disp(' Done.') %end @@ -253,7 +254,7 @@ function matl(varargin) %disp('--') %disp(repmat('-',size(str))) pause end - matl_run(S, pOutFile, cOutFileNoExt, [], isMatlab) % ...NoExt because a file name without extension is + matl_run(S, pOutFile, cOutFileNoExt, [], isMatlab, useTags) % ...NoExt because a file name without extension is % needed in old Matlab versions end @@ -263,7 +264,7 @@ function matl(varargin) disp('Press any key to run MATL program in debug mode') pause end - matl_run(S, pOutFile, cOutFileNoExt, [S.compileLine], isMatlab) % ...NoExt because a file name without + matl_run(S, pOutFile, cOutFileNoExt, [S.compileLine], isMatlab, useTags) % ...NoExt because a file name without % extension is needed in old Matlab versions end diff --git a/matl_compile.m b/matl_compile.m index 5c1386c..893f32b 100644 --- a/matl_compile.m +++ b/matl_compile.m @@ -1,4 +1,4 @@ -function S = matl_compile(S, F, L, pOutFile, cOutFile, verbose, isMatlab) +function S = matl_compile(S, F, L, pOutFile, cOutFile, verbose, isMatlab, useTags) % % MATL compiler. Compiles into MATLAB code. % Input: struct array with parsed statements. @@ -21,21 +21,41 @@ % % Luis Mendo -global indStepComp -global C +global indStepComp C implicitInputBlock indStepComp = 4; +if verbose + disp(' Generating compiled code') +end + Fsource = {F.source}; % this field of `F` will be used often % Possible improvement: preallocate for greater speed, and modify % appendLines so that C doesn't dynamically grow C = {}; % Cell array of strings. Each cell contains a line of compiled (MATLAB) code -if verbose - disp(' Generating compiled code') +if useTags + strongBegin = ''; + strongEnd = ''; +else + strongBegin = ''; + strongEnd = ''; end +% Define blocks of code that will be reused +implicitInputBlock = {... + 'if ~isempty(nin) && (numel(STACK)+nin(1)<1)' ... + 'implInput = {};' ... + 'for k = 1:1-numel(STACK)-nin(1)' ... + 'implInput{k} = input(implicitInputPrompt,''s'');' ... + 'assert(isempty(regexp(implInput{k}, ''^[^'''']*(''''[^'''']*''''[^'''']*)*[a-zA-Z]{2}'', ''once'')), ''MATL:runtime'', ''MATL run-time error: input not allowed'')' ... + 'if isempty(implInput{k}), implInput{end} = []; else implInput{k} = eval(implInput{k}); end' ... + 'end' ... + 'STACK = [implInput STACK];' ... + 'clear implInput k' ... + 'end'}; + % Include function header [~, name] = fileparts(cOutFile); appendLines(['function ' name], 0) @@ -61,6 +81,7 @@ appendLines('P = pi; Y = inf; N = NaN; M = -1; G = -1j;', 0) % Constants to be used by function code appendLines('defaultInputPrompt = ''> '';', 0); +appendLines('implicitInputPrompt = ''> '';', 0); % Predefine literals for functions if ~isempty(S) plf = cellstr(char(bsxfun(@plus, 'X0', [floor(0:.1:2.9).' repmat((0:9).',3,1)]))).'; % {'X0'...'Z9'} @@ -101,8 +122,18 @@ case 'literal.logicalRowArray' lit = strrep(strrep(S(n).source,'T','true,'),'F','false,'); lit = ['[' lit(1:end-1) ']']; - appendLines(['STACK{end+1} = ' lit ';'], S(n).nesting) + appendLines(['STACK{end+1} = ' lit ';'], S(n).nesting) + case 'metaFunction.inSpec' + appendLines('nin = 0;', S(n).nesting); + appendLines(implicitInputBlock, S(n).nesting); % code block for implicit input + appendLines('S_IN = STACK{end}; STACK(end) = [];', S(n).nesting) + case 'metaFunction.outSpec' + appendLines('nin = 0;', S(n).nesting); + appendLines(implicitInputBlock, S(n).nesting); % code block for implicit input + appendLines('S_OUT = STACK{end}; STACK(end) = [];', S(n).nesting) case 'controlFlow.for' + appendLines('nin = 0;', S(n).nesting); + appendLines(implicitInputBlock, S(n).nesting); % code block for implicit input newLines{1} = sprintf('in = STACK{end}; STACK(end) = []; indFor%i = 0;', S(n).nesting); newLines{2} = sprintf('for varFor%i = in', S(n).nesting); appendLines(newLines, S(n).nesting) @@ -117,6 +148,8 @@ newLines = sprintf('indDoWhile%i = indDoWhile%i+1;', S(n).nesting, S(n).nesting); appendLines(newLines, S(n).nesting+1) case 'controlFlow.while' % 'X`' + appendLines('nin = 0;', S(n).nesting); + appendLines(implicitInputBlock, S(n).nesting); % code block for implicit input newLines = { sprintf('indWhile%i = 0;', S(n).nesting) ... sprintf('condWhile%i = STACK{end};', S(n).nesting) ... 'STACK(end) = [];' ... @@ -125,6 +158,8 @@ newLines = sprintf('indWhile%i = indWhile%i+1;', S(n).nesting, S(n).nesting); appendLines(newLines, S(n).nesting+1) case 'controlFlow.if' % '?' + appendLines('nin = 0;', S(n).nesting); + appendLines(implicitInputBlock, S(n).nesting); % code block for implicit input newLines = { 'in = STACK{end}; STACK(end) = [];' ... 'if in' }; appendLines(newLines, S(n).nesting); @@ -132,12 +167,16 @@ appendLines('else', S(n).nesting) case 'controlFlow.end' % ']' if strcmp(S(S(n).from).type, 'controlFlow.doWhile') + appendLines('nin = 0;', S(n).nesting); + appendLines(implicitInputBlock, S(n).nesting); % code block for implicit input newLines = { sprintf('condDoWhile%i = STACK{end};', S(n).nesting) ... 'STACK(end) = [];' ... 'end' ... sprintf('clear indDoWhile%i', S(n).nesting)}; appendLines(newLines, S(n).nesting) elseif strcmp(S(S(n).from).type, 'controlFlow.while') + appendLines('nin = 0;', S(n).nesting); + appendLines(implicitInputBlock, S(n).nesting); % code block for implicit input newLines = { sprintf('condWhile%i = STACK{end};', S(n).nesting) ... 'STACK(end) = [];' ... 'end' ... @@ -151,11 +190,15 @@ newLines = 'end'; appendLines(newLines, S(n).nesting); else - error('MATL:compiler:internal', 'MATL internal error while compiling statement %s', S(n).source) + error('MATL:compiler:internal', 'MATL internal error while compiling statement %s%s%s', strongBegin, S(n).source, strongEnd) end case 'controlFlow.conditionalBreak' + appendLines('nin = 0;', S(n).nesting); + appendLines(implicitInputBlock, S(n).nesting); % code block for implicit input appendLines('in = STACK{end}; STACK(end) = []; if in, break, end', S(n).nesting) case 'controlFlow.conditionalContinue' + appendLines('nin = 0;', S(n).nesting); + appendLines(implicitInputBlock, S(n).nesting); % code block for implicit input appendLines('in = STACK{end}; STACK(end) = []; if in, continue, end', S(n).nesting) case 'controlFlow.forValue' k = S(S(n).from).nesting; @@ -169,13 +212,17 @@ case 'function' k = find(strcmp(S(n).source, Fsource), 1); % Fsource is guaranteed to contain unique entries. if isempty(k) - error('MATL:compiler', 'MATL error while compiling: function %s in statement number %i not defined in MATL', S(n).source, pOutFile, n, n) + if useTags + error('MATL:compiler', 'MATL error while compiling: function %s%s%s in statement number %i not defined in MATL', strongBegin, S(n).source, strongEnd, pOutFile, n, n) + else + error('MATL:compiler', 'MATL error while compiling: function %s%s%s in statement number %i not defined in MATL', strongBegin, S(n).source, strongEnd, n) + end end appendLines(funWrap(F(k).minIn, F(k).maxIn, F(k).defIn, F(k).minOut, F(k).maxOut, F(k).defOut, ... F(k).consumeInputs, F(k).wrap, F(k).body), S(n).nesting) C = [C strcat(blanks(indStepComp*S(n).nesting), newLines)]; otherwise - error('MATL:compiler:internal', 'MATL internal error while compiling statement %s: unrecognized statement type', S(n).source) + error('MATL:compiler:internal', 'MATL internal error while compiling statement %s%s%s: unrecognized statement type', strongBegin, S(n).source, strongEnd) end end @@ -192,22 +239,22 @@ appendLines('% Define subfunctions', 0) appendLines('', 0) appendLines({... - 'function y = num2str(varargin)'; - 'x = varargin{1}; x = reshape(x, size(x,1),[]);'; - 'if nargin==1 || ischar(varargin{1}) || isnumeric(varargin{2})'; % normal `num2str` function - 'y = builtin(''num2str'', varargin{:});'; - 'else'; % interception - 'fmt = varargin{2}; y = sprintf([fmt ''\n''], x.''); y = regexp(y, ''\n'', ''split''); y = y(1:end-1).'';'; - 'y = cellfun(@fliplr, y, ''uniformoutput'', false); y = char(y); y = fliplr(y);'; - 'y = reshape(y.'',[],size(x,1)).''; y = strtrim(y);'; - 'end'; + 'function y = num2str(varargin)' ... + 'x = varargin{1}; x = reshape(x, size(x,1),[]);' ... + 'if nargin==1 || ischar(varargin{1}) || isnumeric(varargin{2}) || any(imag(x(:)))' ... % normal `num2str` function + 'y = builtin(''num2str'', varargin{:});' ... + 'else' ... % interception + 'fmt = varargin{2}; y = sprintf([fmt ''\n''], x.''); y = regexp(y, ''\n'', ''split''); y = y(1:end-1).'';' ... + 'y = cellfun(@fliplr, y, ''uniformoutput'', false); y = char(y); y = fliplr(y);' ... + 'y = reshape(y.'',[],size(x,1)).''; y = strtrim(y);' ... + 'end' ... 'end'}, 0) % im2col appendLines('', 0) appendLines({... - 'function y = im2col(varargin)'; - 'argin1 = varargin{1}; argin1 = reshape(argin1, size(argin1,1), []);'; - 'y = builtin(''im2col'', argin1, varargin{2:end});'; + 'function y = im2col(varargin)' ... + 'argin1 = varargin{1}; argin1 = reshape(argin1, size(argin1,1), []);' ... + 'y = builtin(''im2col'', argin1, varargin{2:end});' ... 'end'}, 0) end @@ -239,19 +286,22 @@ % Code generated at the beginning of functions: check S_IN and S_OUT, % get inputs, prepare outputs, consume inputs if applicable. % `consume` indicates if inputs should be removed from the stack +global implicitInputBlock newLines = { ... sprintf('if isempty(S_IN), S_IN = %s; end', defIn) ... sprintf('if isnumeric(S_IN) && numel(S_IN) == 1, if S_IN < %s || S_IN > %s, error(''MATL:runner'', ''MATL run-time error: incorrect input specification''), end', minIn, maxIn) ... sprintf('elseif islogical(S_IN), if nnz(S_IN) < %s || nnz(S_IN) > %s, error(''MATL:runner'', ''MATL run-time error: incorrect input specification''), end', minIn, maxIn) ... 'else error(''MATL:runner'', ''MATL run-time error: input specification not recognized''), end' ... - 'if isnumeric(S_IN), nin = -S_IN+1:0; else nin = find(S_IN)-numel(S_IN); end' ... + 'if isnumeric(S_IN), nin = -S_IN+1:0; else nin = find(S_IN)-numel(S_IN); end'}; +newLines = [newLines implicitInputBlock]; % code block for implicit input +newLines = [newLines, {... 'in = STACK(end+nin);' ... sprintf('if isempty(S_OUT), S_OUT = %s; end', defOut) ... sprintf('if isnumeric(S_OUT) && numel(S_OUT) == 1, if S_OUT < %s || S_OUT > %s, error(''MATL:runner'', ''MATL run-time error: incorrect output specification''), end', minOut, maxOut) ... sprintf('elseif islogical(S_OUT), if numel(S_OUT) < %s || numel(S_OUT) > %s, error(''MATL:runner'', ''MATL run-time error: incorrect output specification''), end', minOut, maxOut) ... 'else error(''MATL:runner'', ''MATL run-time error: output specification not recognized''), end' ... 'if isnumeric(S_OUT), nout = S_OUT; else nout = numel(S_OUT); end' ... - 'out = cell(1,nout);' }; + 'out = cell(1,nout);' }]; % For logical S_IN we use nnz (the inputs are picked from the stack), but % for logical S_OUT we use numel (the function is called with that many outputs) if consume diff --git a/matl_disp.m b/matl_disp.m index 726c501..8f5eade 100644 --- a/matl_disp.m +++ b/matl_disp.m @@ -51,6 +51,8 @@ function matl_disp(S, F, indentBase, indentStep, indentCommentSymbol, indentComm texts(ismember(Stype, {'literal.logicalRowArray'})) = {'logical row array literal'}; texts(ismember(Stype, {'literal.cellArray'})) = {'cell array literal'}; texts(ismember(Stype, {'literal.string'})) = {'string literal'}; + texts(strcmp(Stype, 'metaFunction.inSpec')) = {'input specification'}; + texts(strcmp(Stype, 'metaFunction.outSpec')) = {'output specification'}; texts(strcmp(Stype, 'controlFlow.for')) = {'for'}; texts(strcmp(Stype, 'controlFlow.doWhile')) = {'do...while'}; texts(strcmp(Stype, 'controlFlow.while')) = {'while'}; diff --git a/matl_help.m b/matl_help.m index 6c233bb..6cc7675 100644 --- a/matl_help.m +++ b/matl_help.m @@ -1,4 +1,4 @@ -function matl_help(H, strHelp, verbose, isMatlab, verNum) +function matl_help(H, strHelp, verbose, useTags) % % MATL help. % @@ -9,35 +9,44 @@ function matl_help(H, strHelp, verbose, isMatlab, verNum) if verbose disp('MATL help:') end + +if useTags + strongBegin = ''; + strongEnd = ''; +else + strongBegin = ''; + strongEnd = ''; +end + if isempty(strHelp) || strcmp(strHelp,'help') % empty string: show help usage and return if verbose - disp(' General help') - disp(' ') + fprintf(' General help\n') + fprintf('\n') end - disp('matl usage:') - disp('First input: options:') - disp(' -p: parse') - disp(' -l: listing. Numeric options specify format') - disp(' -e: listing with comments. Numeric options specify format') - disp(' -c: compile') - disp(' -r: run (default)') - disp(' -d: debug') - disp(' -f: use file') - disp(' -v: verbose') - disp(' -h: help.') - disp('Second input: string:') - disp(' Contains source code, file name or search text') - disp(' Source code or file name can be omitted. In that case they are introduced later') - disp(' Search text can be a name of function or statement, or a word.') + fprintf('%smatl%s usage:\n', strongBegin, strongEnd) + fprintf('First input: options:\n') + fprintf(' %s-p%s: parse\n', strongBegin, strongEnd) + fprintf(' %s-l%s: listing. Numeric options specify format\n', strongBegin, strongEnd) + fprintf(' %s-e%s: listing with comments. Numeric options specify format\n', strongBegin, strongEnd) + fprintf(' %s-c%s: compile\n', strongBegin, strongEnd) + fprintf(' %s-r%s: run (default)\n', strongBegin, strongEnd) + fprintf(' %s-d%s: debug\n', strongBegin, strongEnd) + fprintf(' %s-f%s: use file\n', strongBegin, strongEnd) + fprintf(' %s-v%s: verbose\n', strongBegin, strongEnd) + fprintf(' %s-h%s: help.\n', strongBegin, strongEnd) + fprintf('Second input: string:\n') + fprintf(' Contains source code, file name or search text\n') + fprintf(' Source code or file name can be omitted. In that case they are introduced later\n') + fprintf(' Search text can be a name of function or statement, or a word.\n') return elseif numel(strHelp)==1 || (numel(strHelp)==2 && any(strHelp(1)=='XYZ')) % search in source if verbose - disp(' Searching for statement with exact matching') + fprintf(' Searching for statement with exact matching\n') end ind = find(strcmp(H.sourcePlain, strHelp)); % exact search in source elseif ~isempty(strHelp) % search in comment or description if verbose - disp(' Searching for text, case-insensitive, partial matching') + fprintf(' Searching for text, case-insensitive, partial matching\n') end ind = find(~cellfun(@isempty, strfind(lower(H.comm), lower(strHelp))) |... ~cellfun(@isempty, strfind(lower(H.descrPlain), lower(strHelp)))); % partial, case-insentive search in comment and description @@ -46,7 +55,7 @@ function matl_help(H, strHelp, verbose, isMatlab, verNum) if verbose && ~isempty(ind) disp(' ') end -if isMatlab && (verNum(1)>7 || (verNum(1)==7 && verNum(2)>=13)) +if useTags descrFieldName = 'descr'; sourceFieldName = 'source'; else diff --git a/matl_parse.m b/matl_parse.m index bb9ac63..a69abf1 100644 --- a/matl_parse.m +++ b/matl_parse.m @@ -1,4 +1,4 @@ -function S = matl_parse(s) +function S = matl_parse(s, useTags) % % MATL parser. % @@ -16,6 +16,13 @@ LF = char(10); % line feed in ASCII CR = char(13); % line feed in ASCII +if useTags + strongBegin = ''; + strongEnd = ''; +else + strongBegin = ''; + strongEnd = ''; +end % Parse to separate into statements @@ -72,9 +79,9 @@ % Consume until ]. There may be other [ and ] in between (although it would be a waste of characters), % so consume until the number of [ minus ] reaches 0 [ini, fin] = regexp(s(pos:end), '^\[([^\[\]]*\[[^\[\]]*\])*[^\[\]]*\]', 'once'); - assert(ini==1, 'MATL:parser:internal', 'MATL internal error while parsing array literal') + assert(isequal(ini,1), 'MATL:parser', 'MATL error while parsing: array literal not well formed') if ~validateArray(s(pos:pos-1+fin)) - error('MATL:parser:internal', 'Content not allowed in MATL array literal') + error('MATL:parser', 'Content not allowed in MATL array literal') end S(n).type = 'literal.array'; S(n).source = s(pos:pos-1+fin); @@ -86,7 +93,7 @@ fin = find(~cumsum((s(pos:end)=='{')-(s(pos:end)=='}')),1); assert(~isempty(fin), 'MATL:parser', 'MATL error while parsing: cell array literal not closed') if ~validateArray(s(pos:pos-1+fin)) - error('MATL:parser:internal', 'Content not allowed in MATL cell array literal') + error('MATL:parser', 'Content not allowed in MATL cell array literal') end S(n).type = 'literal.cellArray'; S(n).source = s(pos:pos-1+fin); @@ -100,7 +107,7 @@ % `c` (`^''([^'']|'''')*?''(?!'')`) indicates string and % `n` (`[+-]?(\d+\.?\d*|\d*\.?\d+)(e[+-]?\d+)?j?`) indicates number assert(~isempty(ini), 'MATL:parser', 'MATL error while parsing: string literal not closed') - assert(ini==1, 'MATL:parser:internal', 'MATL internal error while parsing string/colon array literal') + assert(isequal(ini,1), 'MATL:parser:internal', 'MATL internal error while parsing string/colon array literal') if any(s(pos:pos-1+fin)==':') % It's a (char) colon array literal S(n).type = 'literal.colonArray.char'; else % It's a string @@ -110,12 +117,24 @@ S(n).nesting = parseNesting; pos = pos + fin; n = n + 1; - elseif any(s(pos)==['!#$&()*+-/:;<=>\^_|~' 'A':'W' 'a':'z']) + elseif any(s(pos)==['!&()*+-/:;<=>\^_|~' 'A':'W' 'a':'z']) S(n).type = 'function'; S(n).source = s(pos); S(n).nesting = parseNesting; pos = pos + 1; n = n + 1; + elseif s(pos)=='$' + S(n).type = 'metaFunction.inSpec'; + S(n).source = s(pos); + S(n).nesting = parseNesting; + pos = pos + 1; + n = n + 1; + elseif s(pos)=='#' + S(n).type = 'metaFunction.outSpec'; + S(n).source = s(pos); + S(n).nesting = parseNesting; + pos = pos + 1; + n = n + 1; elseif s(pos)=='"' % for % We use fields "from", "end" and "else" to keep track of the % structure of loops and conditional branches. @@ -226,7 +245,7 @@ n = n + 1; elseif s(pos)=='%' % consume until LF or CR. Don't store in S [ini, fin] = regexp(s(pos:end),'^%[^\r\n]*[\r\n]?'); - assert(ini==1, 'MATL:parser:internal', 'MATL internal error while parsing comment literal') + assert(isequal(ini,1), 'MATL:parser:internal', 'MATL internal error while parsing comment literal') pos = pos + fin; % There's no statement. Just move `pos` forward. Statement count n is not incremented elseif any(s(pos)==[', ' LF CR]) % do nothing, just consume (but that @@ -259,7 +278,7 @@ error('MATL:parser', 'MATL error while parsing: ''conditional continue'' is not within any ''for'' loop') end elseif any(s(pos+1)==' ') % Not currently used after X. We can filter here or leave it to the compiler - error('MATL:parser', 'MATL error while parsing: %s not recognized at position %d', s([pos pos+1]), pos) + error('MATL:parser', 'MATL error while parsing: %s%s%s not recognized at position %d', strongBegin, s([pos pos+1]), strongEnd, pos) else S(n).type = 'function'; S(n).source = s([pos pos+1]); @@ -269,7 +288,7 @@ n = n + 1; elseif s(pos)=='Y' && pos%s not recognized at position %d', s([pos pos+1]), pos) + error('MATL:parser', 'MATL error while parsing: %s%s%s not recognized at position %d', strongBegin, s([pos pos+1]), strongEnd, pos) else S(n).type = 'function'; S(n).source = s([pos pos+1]); @@ -279,7 +298,7 @@ n = n + 1; elseif s(pos)=='Z' && pos%s not recognized at position %d', s([pos pos+1]), pos) + error('MATL:parser', 'MATL error while parsing: %s%s%s not recognized at position %d', strongBegin, s([pos pos+1]), strongEnd, pos) else S(n).type = 'function'; S(n).source = s([pos pos+1]); @@ -288,11 +307,11 @@ pos = pos + 2; n = n + 1; elseif any(s(pos)=='''') % Not allowed. - error('MATL:parser', 'MATL error while parsing: %s not recognized at position %d', s(pos), pos) + error('MATL:parser', 'MATL error while parsing: %s%s%s not recognized at position %d', strongBegin, s(pos), strongEnd, pos) elseif any(s(pos)=='XYZ') && pos==L - error('MATL:parser', 'MATL error while parsing: %s not recognized at position %d', s(pos), pos) + error('MATL:parser', 'MATL error while parsing: %s%s%s not recognized at position %d', strongBegin, s(pos), strongEnd, pos) else - error('MATL:parser', 'MATL error while parsing: unknown character %s at position %d', s(pos), pos) + error('MATL:parser', 'MATL error while parsing: unknown character %s%s%s at position %d', strongBegin, s(pos), strongEnd, pos) end end @@ -326,7 +345,7 @@ if isfield(S,'end') && any(cellfun(@(x) isequal(x,0), {S.end})) unclosed = find(cellfun(@(x) isequal(x,0), {S.end}), 1); - error('MATL:parser', 'MATL error while parsing: %s statement has no matching ]', S(unclosed).source) + error('MATL:parser', 'MATL error while parsing: %s%s%s statement has no matching ]', strongBegin, S(unclosed).source, strongEnd) end end diff --git a/matl_run.m b/matl_run.m index 57e99a7..77fc4fd 100644 --- a/matl_run.m +++ b/matl_run.m @@ -1,4 +1,4 @@ -function matl_run(S, pOutFile, cOutFileNoExt, dbstopLines, isMatlab) +function matl_run(S, pOutFile, cOutFileNoExt, dbstopLines, isMatlab, useTags) % % MATL runner and debugger: runs MATL code that has been compiled into MATLAB code. Catches MATLAB % errors and references them to the MATL statement that caused them. @@ -48,7 +48,11 @@ function matl_run(S, pOutFile, cOutFileNoExt, dbstopLines, isMatlab) if ~isempty(ME.stack(h)) k = ME.stack(h).line; n = find([S(:).compileLine]<=k, 1, 'last'); - fprintf(2, 'MATL run-time error: The following MATLAB error refers to statement number %i: %s\n', pOutFile, n, n, S(n).source); + if useTags + fprintf(2, 'MATL run-time error: The following MATLAB error refers to statement number %i: %s\n', pOutFile, n, n, S(n).source); + else + fprintf(2, 'MATL run-time error: The following MATLAB error refers to statement number %i: %s\n', n, S(n).source); + end fprintf(2, '---\n'); else error('MATL:runner:internal', 'MATL internal error while running compiled file. More information follows'); diff --git a/preLit.mat b/preLit.mat index bea1d36..faf2f2f 100644 Binary files a/preLit.mat and b/preLit.mat differ diff --git a/preLit.txt b/preLit.txt index ec4c0c9..68f5359 100644 --- a/preLit.txt +++ b/preLit.txt @@ -148,16 +148,8 @@ X8 X9 -1 'shuffle' -2 'default' -3 'twister' -4 'simdTwister' -5 'combRecursive' -6 'multFibonacci' -10 'v5uniform' -11 'v5normal' -12 'v4' -20 'seed' +1 '%.16g ' +10 'seed' Y0