Skip to content
Permalink
Browse files

Compatibility with Octave

The compiler now works with Octave. I have been able to run all example
programs I have tried.  However, this doesn't assure complete
compatibility; more extensive testing needs to be done. Also, HTML tags
in online help need to be removed in Octave (also in old Matlab
versions) because they are not displayed properly. That will be done in
a next release.
  • Loading branch information...
lmendo committed Dec 28, 2015
1 parent 9150028 commit 77a5eba228ccedec8ac0d58d0f1842aba03858cc
Showing with 66 additions and 22 deletions.
  1. +8 −3 matl.m
  2. +25 −4 matl_compile.m
  3. +4 −1 matl_parse.m
  4. +29 −14 matl_run.m
11 matl.m
@@ -20,6 +20,11 @@ function matl(varargin)
helpFile = 'help.mat';
matlInputPrompt = ' > ';

version = ver;
indMainName = find(ismember({version.Name}, {'MATLAB','Octave'}));
isMatlab = strcmp(version(indMainName).Name, 'MATLAB'); % 1 if Matlab, 0 if Octave
verNum = version(indMainName).Version; % version number as a string

if numel(varargin)==0
options = 'r';
inputNeeded = true;
@@ -233,7 +238,7 @@ function matl(varargin)
if verbose
disp('Compiling program')
end
S = matl_compile(S, F, L, pOutFile, cOutFile, verbose);
S = matl_compile(S, F, L, pOutFile, cOutFile, verbose, isMatlab);
%if verbose
% disp(' Done.')
%end
@@ -247,7 +252,7 @@ function matl(varargin)
%disp('--') %disp(repmat('-',size(str)))
pause
end
matl_run(S, pOutFile, cOutFileNoExt, []) % ...NoExt because a file name without extension is
matl_run(S, pOutFile, cOutFileNoExt, [], isMatlab) % ...NoExt because a file name without extension is
% needed in old Matlab versions
end

@@ -257,7 +262,7 @@ function matl(varargin)
disp('Press any key to run MATL program in debug mode')
pause
end
matl_run(S, pOutFile, cOutFileNoExt, [S.compileLine]) % ...NoExt because a file name without
matl_run(S, pOutFile, cOutFileNoExt, [S.compileLine], isMatlab) % ...NoExt because a file name without
% extension is needed in old Matlab versions
end

@@ -1,4 +1,4 @@
function S = matl_compile(S, F, L, pOutFile, cOutFile, verbose)
function S = matl_compile(S, F, L, pOutFile, cOutFile, verbose, isMatlab)
%
% MATL compiler. Compiles into MATLAB code.
% Input: struct array with parsed statements.
@@ -48,10 +48,11 @@
appendLines('% Set initial conditions', 0)
appendLines('warningState = warning;', 0);
appendLines('format compact; format long; warning(''off'',''all'');', 0) % clc
if exist('rng', 'file') % in case an old Matlab version is used
if isMatlab && exist('rng', 'file') % recent Matlab version
appendLines('rng(''shuffle'')', 0)
else
warning('MATL has not been able to seed random number generator')
elseif isMatlab % old Matlab version
appendLines('rand(''seed'',sum(clock)); randn(''seed'',sum(clock))');
% else % Octave: seeds are set randomly automatically by Octave
end
appendLines('diary off; delete defout; diary defout', 0)
% For arrays with brackets or curly braces: F = false; T = true;
@@ -182,6 +183,26 @@
appendLines('', 0)
appendLines('% Set final conditions', 0)
appendLines('diary off; warning(warningState);', 0);
appendLines('', 0)
appendLines('end', 0) % close function, in case there are subfunctions

% Define subfunctions
if ~isMatlab
appendLines('', 0)
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';
'end'}, 0)
end

if verbose
fprintf(' Writing to file ''%s''\n', cOutFile')
@@ -299,7 +299,10 @@
% Include implicit statements in source code

% Mark existing statements as not implicit
[S(:).implicit] = deal(false);
%[S(:).implicit] = deal(false); % doesn't work in Octave (4.0.0)
for s = 1:numel(S)
S(s).implicit = false;
end

% Implicit ]
while parseNesting % While there is some loop or branch yet to be closed
@@ -1,4 +1,4 @@
function matl_run(S, pOutFile, cOutFile, dbstopLines)
function matl_run(S, pOutFile, cOutFileNoExt, dbstopLines, isMatlab)
%
% 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.
@@ -10,26 +10,41 @@ function matl_run(S, pOutFile, cOutFile, dbstopLines)
% Luis Mendo

if ~isempty(dbstopLines) % debug mode
for line = dbstopLines
eval([ 'dbstop in ' cOutFile ' at ' num2str(line) ])
if isMatlab
for line = dbstopLines
eval([ 'dbstop in ' cOutFileNoExt ' at ' num2str(line) ])
end
openvar('STACK')
openvar('S_IN'), openvar('S_OUT')
openvar('CB_H'), openvar('CB_I'), openvar('CB_J'), openvar('CB_K'), openvar('CB_L')
openvar('STACK') % This is to bring this variable to front
else % Octave
for line = dbstopLines
dbstop(cOutFileNoExt, line);
end
% No `openvar` in Octave (4.0.0)
end
openvar('STACK')
openvar('S_IN'), openvar('S_OUT')
openvar('CB_H'), openvar('CB_I'), openvar('CB_J'), openvar('CB_K'), openvar('CB_L')
openvar('STACK') % This is to bring this variable to front
else % non-debug mode
if exist(cOutFile,'file')
eval([ 'dbclear in ' cOutFile ]) % `eval`: I know, I know...
if isMatlab
if exist(cOutFileNoExt,'file')
eval([ 'dbclear in ' cOutFileNoExt ]) % `eval`: I know, I know...
end
else % Octave
if exist(cOutFileNoExt,'file')
dbclear(cOutFileNoExt);
delete([cOutFileNoExt '.m']) % Sometimes it looks like an old version of the file is run
% instead of the new compiled one. So I'm deleting the file just in case
end
end
end

try
run(cOutFile)
% run(cOutFileNoExt) % This doesn't seem to worl in Octave (4.0.0)
evalin('caller', [cOutFileNoExt ';']);
catch ME
[~, cOutFileNoExt] = fileparts(cOutFile);
h = find(strcmp({ME.stack.name},cOutFileNoExt),1); % first error that refers to cOutFile
% This is necessary because the error may have been issued not by cOutFile directly, but
% by a function called by cOutFile
h = find(strcmp({ME.stack.name},cOutFileNoExt),1); % first error that refers to cOutFileNoExt
% This is necessary because the error may have been issued not by cOutFileNoExt directly, but
% by a function called by cOutFileNoExt
if ~isempty(ME.stack(h))
k = ME.stack(h).line;
n = find([S(:).compileLine]<=k, 1, 'last');

0 comments on commit 77a5eba

Please sign in to comment.
You can’t perform that action at this time.