         
       if callback
         scriptElem.onload = scriptElem.onreadystatechange = ->
-          rs = @readyState;
+          rs = @readyState
           return undefined if rs and rs isnt 'complete' and rs isnt 'loaded'
           callback()
         
       firstScriptElem = root.document.getElementsByTagName('script')[0]
       firstScriptElem.parentNode.insertBefore scriptElem, firstScriptElem
+    else
+      # Make sure require is available
+      if require
+        require filename
+        callback()
+
+  # Cache and queue definition
+  cache = {}
+  queue = {}
+
+  # Molo base object
+  root.molo = {}
+  
+  # Debug functions
+  #root.molo.getCache = -> cache
+  #root.molo.getQueue = -> queue
+
+  # Molo configuration
+  root.molo.basePath = ''
+  root.molo.paths = {}
+  root.molo.defaultContext = root
+
+  
+  # Define function
+  root.molo.define = root.define = (name, dependencies, factory) ->
+    if cache[name]
+      throw new TypeError "A module called #{name} has already been evaluated. Please choose a different name."
       
-  moloDefine = (name, body) ->
-    # Abort if no name or no body
-    return unless name or body
+    if cache[name]
+      throw new TypeError "A module called #{name} has already been defined. Please choose a different name."
+      
+    unless Array.isArray dependencies
+      if typeof dependencies is 'object' or typeof dependencies is 'function'
+        [dependencies, factory] = [factory, dependencies]
+      
+    unless dependencies then dependencies = []
     
-    # If name is a function, then just call the function
-    if typeof name is 'function' then return name.apply @
+    # Add to cache directly if no dependencies
+    if dependencies.length is 0
+      if typeof factory is 'function'
+        cache[name] = factory.call root.molo.defaultContext
+      else
+        cache[name] = factory
+      return
+      
+    queue[name] = {dependencies, factory}
     
-    # If body, add it to the cache directly, else queue it
-    # Special case: body is allowed to be an object (add it to cache)
-    if typeof body is 'object' then return cache[name] = body
     
-    # If function, call the function and add it to the cache
-    if typeof body is 'function' then return cache[name] = body()
+  # Require function
+  root.molo.require = root.require = (name, callback, context = root.molo.defaultContext) ->
+    # If a single dependency has been declared as a string, make it into an array
+    if typeof name is 'string' then name = [name]
     
-    queue[name] = define
+    # Abort condition
+    return unless Array.isArray name
     
-  moloRequire = (name, callback) ->
-    if Object.hasOwnProperty.call cache, name then return callback cache[name]
-    
-    if Object.hasOwnProperty.call queue, name
-      name
-    
-
-  moloFunc = (name, defines) ->
-    # TODO: Add module name always to queue and remove it if all dependencies have been met
-    # Currently, the module will only be added if it has any depedencies and cannot be
-    # resolved directly
-    
-    # Skip flag to skip the rest of the function
-    skipFunc = false
-    
-    defObject = {}
-
-    # If name is not a string, it's an anonymous module (Put defines parameter in the correct order)
-    if typeof name isnt 'string'
-      # If name is an array, just load dependencies
-      if Array.isArray(name) 
-        if Object.keys(defines).length > 0
-          defines.require = name
+    for i in name
+      do (i) ->
+        # Get the result of cached dependencies
+        cacheDeps = []
+                
+        if queue[i]
+          depIndex = 0
+          depLength = queue[i].dependencies.length
+          
+          depsLoaded = ->
+            if depIndex is depLength
+              cache[i] = queue[i].factory.apply context, cacheDeps
+              
+          updateDeps = ->
+            depIndex++
+            depsLoaded()
+          
+          for dep in queue[i].dependencies
+            # Need to check for hasOwnProperty
+            # Checking for cache[i] is not strict enough
+            # because a module could have undefined, null, 0 or an empty string
+            # as its export value
+            if Object.hasOwnProperty.call cache, dep
+              cacheDeps.push cache[dep]
+              depIndex++
+              depsLoaded()
+            else
+              root.molo.require i, updateDeps, context
         else
-          defines =
-            require: name
-
-        skipFunc = true
-      else 
-        [name, defines] = [undefined, name]
-
-    # Skip if no factory has been defined
-    return undefined unless defines
-
-    # Get properties from defines if it's an object, else they are no dependencies and take the function as the factory
-    if typeof defines is 'function' then define = defines else {define, require: deps, context} = defines
-
-    # Default parameters, if they have not been defined yet
-    deps = [] unless deps?
-    context = @ unless context?
-
-    # If a single dependency has been declared as a string, make it into an array
-    if typeof deps is 'string' then deps = [deps]
-
-    # Get the result of cached dependencies
-    cacheDeps = []
-
-    for i in deps
-      # Need to check for hasOwnProperty
-      # Checking for cache[i] is not strict enough
-      # because a module could have undefined, null, 0 or an empty string
-      # as its export value
-      if Object.hasOwnProperty.call cache, i
-        cacheDeps.push cache[i]
-      else
-        # Plugin functionality
-        pluginName = i.split('!')[1]
-        
-        scriptLoader = root.molo.scriptLoader
-        
-        # If a script is defined as 'my/script!' it will try to resolve the 
-        # dependency on the same page
-        scriptLoader = false if pluginName is ''
-        
-        if scriptLoader
           if isJavaScriptFile(root.molo.paths[name])
             # If the path is complete (e.g. 'js/lib/mymodule.js') take that as a path
             scriptPath = root.molo.paths[name]

'use strict';

# ES 5 compability functions
Object.keys or= (o) -> name for own name of o
Array.isArray or= (a) -> a.push is Array.prototype.push and a.length?

# CommonJS flag
isCommonJS = exports?

# Function to check for JavaScript file ending
hasExtension = (filename, extension) -> 
  return undefined unless filename?
  
  filename.lastIndexOf(extension) is filename.length - extension

isJavaScriptFile = (filename) -> hasExtension filename, '.js'

# Wrapper function
do (root = module?.exports ? this) ->
  cache = {}
  queue = {}
  pathSep = '/'
  
  loadScriptFile = (filename, callback) ->
    unless isCommonJS
      scriptElem = root.document.createElement 'script'
      
      scriptElem.async = true

                prePath = root.molo.paths[p]

            scriptPath = if prePath then "#{prePath}#{pathSep}#{i}.js" else "#{i}.js"
        
          loadScriptFile scriptPath, ->
            #root.molo.require i, callback, context
        
        
  # Additional export functions
  
  # Delete a single module from cache, which forces it to
  # reload this module if it comes up as a dependency the
  # next time
  root.molo.delete = (name) ->
    delete cache[name] if cache[name]
    delete queue[name] if queue[name]

  # Completely clear all caches
  root.molo.clear = ->
    cache = {}
    queue = {}
    
  
  # Molo main shorthand
  mainHasBeenCalled = false
  
  root.molo.main = (name, callback) ->
    if mainHasBeenCalled then throw new TypeError('molo.main can only be called once.')

    root.molo.require name, callback
    
    moloHasBeenCalled = true
    

  # Alternative module decleration
  root.unit = (name, body) ->
    {requires, defines} = body
    
    root.molo.define name, requires, defines
