Skip to content

generate documentation using Doxygen #25

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 7 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2,493 changes: 2,493 additions & 0 deletions Doxyfile

Large diffs are not rendered by default.

15 changes: 6 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
SaC standard library
====================


[![build status](https://travis-ci.org/SacBase/Stdlib.svg?branch=master)](https://travis-ci.org/SacBase/Stdlib) [![contributions welcome](https://img.shields.io/badge/contributions-welcome-brightgreen.svg)](https://github.com/SacBase/Stdlib/issues)

This repository consists of SaC modules with basic functionality like
arithmetic, stdio, etc; which together form a standard library of SaC
language.
Here are provided the modules and classes that consitute the standard
library of the SaC programming language.

Build instructions
==================
Expand All @@ -15,14 +13,14 @@ To build the system one requires an operational [CMake](https://cmake.org/) >= 3
[Flex](http://flex.sourceforge.net/), and [Bison](https://www.gnu.org/software/bison/).

An example on how to build the library:
```bash
```sh
$ cd Stdlib
$ git submodule init
$ git submodule update
$ mkdir build
$ cd build
$ cmake ..
$ make -j4 #you should have roughly 2GB per thread :-)
$ make -j4 # you should have roughly 2GB per thread :-)
```

If you like you can also install the stdlib into `/usr/local` with `make
Expand All @@ -32,13 +30,12 @@ build automatically.
**NOTE:** *When pulling the latest commit, remember to run `git submodule
update` or you will be missing changes to the `cmake-common` repository.*

Variables that can be passed to CMake
=========================================
### Variables that can be passed to CMake

When running CMake it is possible to pass the following variables:
* `-DTARGETS=x;y;z` --- build stdlib for targets x, y and z. (Defaults to `seq;mt_pth`)
* `-DBUILDGENERIC=ON|OFF` --- build stdlib without using architecture specific optimisations
* (useful when creating distributable packages). (Default is `OFF`)
(useful when creating distributable packages). (Default is `OFF`)
* `-DSAC2C_EXEC=/path/to/sac2c` --- specify `sac2c` executable directly. Otherwise CMake will
try to find `sac2c` on yout PATH.
* `-DLINKSETSIZE=n` --- set `-linksetsize n` when calling `sac2c`. This option is responsible
Expand Down
140 changes: 140 additions & 0 deletions scripts/sac2doxygen.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
#!/usr/bin/env python3

'''
This script translates SaC code into a format that is reasonably parsable by Doxygen's C/C++ mode.
This reformating mainly replaces SaC-specific keywords with C-specific ones, or removes these. Some
attemps have been made to convert certain SaC syntax into something C-like (this formating makes no
difference to the underlying code, we *do not* expose sourcecode within the documentation. We are
only interested in Doxygen comments and the function signitures and other fields within modules.)

One nastiness comes from Doxygen not supporting abitrary symbols for function names. It allides these
implicitly, meaning if left unhandled, you get functions with strange names. We intentionally translate
such names into english and automatically add a Doxygen comment about this (FYI for the user).

The SaC source files are first passed through CPP, before being passed to Doxygen. We do this
so that we have all possible functions defined, meaning that documentation is more complete.
Additionally, this step removes all macros, some of which Doxygen does not handle well (SaCish macros
can be hellish).
'''

import sys
import re
import argparse
import subprocess
import tempfile

## Fixed patterns
# comments
comment = re.compile (r'^\s*(?:\/\/|\/\*|\*)')
# change external to extern
extern = re.compile (r'^\s*external\s')
# match SaC specifc keywards
sacisms = re.compile (r'^\s*(?:module|specialize|class|use|export|import)\s')
sacclass = re.compile (r'^\s*class\s+(\w+);')
eclasstype = re.compile (r'^\s*external\sclasstype')
classtype = re.compile (r'^\s*classtype\s')
objdef = re.compile (r'^\s*(?:external)?\s*objdef\s')
# match SaC functions
funcs = re.compile (r'(?:\w|\.)+(?:\[[\.\+\*,\d]+\])?\s+[\w\d_\-\+\\%]+\s*\([^\(\)]*\)')
funcargs = re.compile (r'\([^\(\)]*\)')
# match function names as symbols
symbfuncs = re.compile (r'\s(?:!|~|\^|&|&&|<<|>>|\||\|\||!|<|<=|>|>=|==|!=|\+|\+\+|\-|\-\-|\*|\/|%)\s*\([^\(\)]*\)')

# globals
CLASS = ''

def clean_line (line):
global CLASS
if re.match (comment, line):
# skip any line that looks like a comment
return (line, False)
ma = re.match (sacclass, line)
if ma:
# capture class name for later use
CLASS = ma.group(1)
if re.match (sacisms, line):
if not re.search (r';', line):
# drop the next line
return ('', True)
else:
# delete only this line
return ('', False)
if CLASS:
line = re.sub (eclasstype, r'typedef classtype {}'.format(CLASS), line)
line = re.sub (classtype, r'typedef classtype ', line)
line = re.sub (objdef, r'', line)
line = re.sub (extern, r'extern ', line)
if re.search (symbfuncs, line):
print ('/** @note The name of the function has been altered for documentation reasons, **make sure to use the appropriate symbol instead**, e.g. _operator+_ -> _+_ */')
# we have to apply these throughout, as some functions might appear all on one line
line = re.sub (r'\s\+\s*\(', r' operator+ (', line)
line = re.sub (r'\s\+\+\s*\(', r' operator++ (', line)
line = re.sub (r'\s\-\s*\(', r' operator- (', line)
line = re.sub (r'\s\-\-\s*\(', r' operator-- (', line)
line = re.sub (r'\s\/\s*\(', r' operator/ (', line)
line = re.sub (r'\s\*\s*\(', r' operator* (', line)
line = re.sub (r'\s\%\s*\(', r' operator% (', line)
line = re.sub (r'\s<\s*\(', r' operator< (', line)
line = re.sub (r'\s<=\s*\(', r' operator<= (', line)
line = re.sub (r'\s>\s*\(', r' operator> (', line)
line = re.sub (r'\s>=\s*\(', r' operator>= (', line)
line = re.sub (r'\s==\s*\(', r' operator== (', line)
line = re.sub (r'\s!=\s*\(', r' operator!= (', line)
line = re.sub (r'\s\|\|\s*\(', r' operator|| (', line)
line = re.sub (r'\s&&\s*\(', r' operator&& (', line)
line = re.sub (r'\s!\s*\(', r' operator! (', line)
line = re.sub (r'\s&\s*\(', r' operator& (', line)
line = re.sub (r'\s\|\s*\(', r' operator| (', line)
# these ones are not common (used at all?)
line = re.sub (r'\s<<\s*\(', r' operator<< (', line)
line = re.sub (r'\s>>\s*\(', r' operator>> (', line)
line = re.sub (r'\s\^\s*\(', r' operator^ (', line)
line = re.sub (r'\s~\s*\(', r' operator~ (', line)
if re.search (funcs, line):
# found function, lets remove commas between return types
for m in re.finditer (funcargs, line):
repl = m.group(0).replace (',', '?COMMA?')
line = line.replace (m.group(0), repl)
line = line.replace (',', '')
line = line.replace ('?COMMA?', ',')
# doxygen does not handle va_args in return type
# XXX this is a kludge
line = line.replace ('... ', 'VARGS ')
return (line, False)

if __name__ == '__main__':
parser = argparse.ArgumentParser(description='Clean SaC (and xSaC) source file for Doxygen parsing')
parser.add_argument('input', metavar='FILE', type=str,
help='SaC source file (use \'-\' for stdin)')
parser.add_argument('-I', '--include', type=str, action='append', default=['.','include','src/include'],
help='Include path for CPP (default: %(default)s)')
parser.add_argument('-D', '--define', type=str, action='append', default=[],
help='Macro definition for CPP')

args = parser.parse_args()

if args.input == '-':
inpf = sys.stdin
else:
#args.input.endswith ('.xsac'):
incs = []
for inc in args.include:
incs.append ('-I' + inc)
defs = []
for deff in args.define:
defs.append ('-D' + deff)
inpf = tempfile.TemporaryFile (mode='w+')
proc = subprocess.run (['cpp', '-C', '-P', '-nostdinc', *incs, *defs, '-DSAC_BACKEND_C99', args.input], stdout=inpf)
inpf.seek (0)
#else:
# inpf = open (args.input)

with inpf as inp:
m = False
for line in inp:
if (m):
# we skip over this line
m = False
continue
out, m = clean_line (line)
print (out.rstrip())
18 changes: 7 additions & 11 deletions src/auxiliary/Benchmarking.sac
Original file line number Diff line number Diff line change
@@ -1,14 +1,8 @@
/* Interface module
*
* void start( Interval& interval);
* void end( Interval& interval);
* void benchThis();
* void printResult( Interval& interval);
* void benchThis();
* Interval getInterval( string interval_name, int interval_number);
* Interval getInterval( int interval_number);
* Interval getInterval( int interval_number);
* void destroyInterval( Interval interval);
/**
* @file
* @defgroup bench Benchmarking Interface
*
* @{
*/

module Benchmarking;
Expand All @@ -23,3 +17,5 @@ import C99Benchmarking: all;
#ifdef SAC_BACKEND_MUTC
import MutcBenchmarking: all;
#endif /* SAC_BACKEND_MUTC */

/** @} */
15 changes: 10 additions & 5 deletions src/auxiliary/C99Benchmarking.sac
Original file line number Diff line number Diff line change
@@ -1,16 +1,20 @@
/* C99 Benchmarking Module
/**
* @file
* @defgroup bench99 C99 Benchmarking
*
* Measures time Intervals in an arbitrary time unit as doubles.
*
* Use getInterval to construct a benchmarking interval object and start and
* end to measure each interval. Take care when start and stop are evaluated
* since this will affect the windows that is measured. The function benchThis
* simply affects the benchmarking object and can be used in inhibit code
* movement. The function printResult dumps the measurement information in a
* since this will affect the windows that is measured. The function benchThis
* simply affects the benchmarking object and can be used in inhibit code
* movement. The function printResult dumps the measurement information in a
* unibench friendly format.
*
* When benchmarking funtions the pragma "noinline" should be specified after
* the function body to inhibit any inlining optimisations.
*
* @{
*/
class C99Benchmarking;
external classtype;
Expand Down Expand Up @@ -428,7 +432,7 @@ void printResults( StringArray::stringArray names, double[.] results)
printf( "### end descriptions\n");
}

/*
/**
* This function simply affects TheBenchmarkObject and nothing else.
* Use it to inhibit code movement. The most common use for benchThis
* is to call it within a function body of a function body that should be
Expand All @@ -450,3 +454,4 @@ external void benchDestroyInterval( Interval interval);
#pragma linksign [1]

#endif /* SAC_BACKEND_C99/CUDA */
/** @} */
38 changes: 20 additions & 18 deletions src/auxiliary/Hiding.sac
Original file line number Diff line number Diff line change
@@ -1,24 +1,26 @@
/*****************************************************************************
/**
* @file
* @defgroup hiding Hiding
*
* file: Hiding.sac
* @brief This module is for hiding type information.
*
* description:
* It is commonly used for static inputs and is intentioned for benchmarking.
*
* This module is for hiding type information.
* It is commonly used for static inputs and is intentioned for benchmarking.
* Some functions take a single argument and hide the value, shape or
* dimensionality information of the input. Others in addition take an
* integer. This allows for calls to inlined kernel functions in a loop
* where where the call must be repeated N times for benchmarking.
*
* Some functions take a single argument and hide the value, shape or
* dimensionality information of the input. Others in addition take an
* integer. This allows for calls to inlined kernel functions in a loop
* where where the call must be repeated N times for benchmarking.
* Here is an example:
* for( i=0 ; i < N ; i}}) {
* res[[i]] = kernel( hideValue( ip1, i), hideValue( ip2, i), ...);
* }
* The above code computes kernel N times even if kernel is inlined.
* Here is an example:
* ~~~~
* for( i=0 ; i < N ; i}}) {
* res[[i]] = kernel( hideValue( ip1, i), hideValue( ip2, i), ...);
* }
* ~~~~
* The above code computes kernel N times even if kernel is inlined.
*
*****************************************************************************/

* @{
*/
module Hiding;

export all;
Expand All @@ -42,7 +44,7 @@ inline \
TYPE[*] hideValue( int i, TYPE[*] in) \
{ \
return( _hideValue_SxA_( i, in)); \
}
}
HIDEVALUE( int)
HIDEVALUE( char)
HIDEVALUE( float)
Expand Down Expand Up @@ -96,4 +98,4 @@ HIDEDIMENSIONALITY( char)
HIDEDIMENSIONALITY( float)
HIDEDIMENSIONALITY( double)
HIDEDIMENSIONALITY( bool)

/** @} */
8 changes: 8 additions & 0 deletions src/auxiliary/Interval.sac
Original file line number Diff line number Diff line change
@@ -1,4 +1,12 @@
/**
* @file
* @defgroup interval Interval Object
* @brief This module provides the Interval classtype
*
* @{
*/
class Interval;
external classtype;

export {Interval};
/** @} */
Loading